blob: 541a3613fee695483ff459be316739ed713eb557 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use {
crate::policy::PolicyError,
clonable_error::ClonableError,
cm_rust::{CapabilityName, EventMode},
fidl_fuchsia_component as fcomponent, fuchsia_zircon_status as zx,
moniker::{AbsoluteMoniker, PartialMoniker},
thiserror::Error,
};
/// Errors produced by `ComponentInstanceInterface`.
#[derive(Debug, Error, Clone)]
pub enum ComponentInstanceError {
#[error("component instance {} not found", moniker)]
InstanceNotFound { moniker: AbsoluteMoniker },
#[error("component manager instance unavailable")]
ComponentManagerInstanceUnavailable {},
#[error("policy checker not found for component instance {}", moniker)]
PolicyCheckerNotFound { moniker: AbsoluteMoniker },
#[error("Failed to resolve `{}`: {}", moniker, err)]
ResolveFailed {
moniker: AbsoluteMoniker,
#[source]
err: ClonableError,
},
}
impl ComponentInstanceError {
pub fn instance_not_found(moniker: AbsoluteMoniker) -> ComponentInstanceError {
ComponentInstanceError::InstanceNotFound { moniker }
}
pub fn cm_instance_unavailable() -> ComponentInstanceError {
ComponentInstanceError::ComponentManagerInstanceUnavailable {}
}
pub fn resolve_failed(moniker: &AbsoluteMoniker, err: impl Into<anyhow::Error>) -> Self {
Self::ResolveFailed { moniker: moniker.clone(), err: err.into().into() }
}
}
/// Errors produced during routing.
#[derive(Debug, Error, Clone)]
pub enum RoutingError {
#[error("Instance identified as source of capability is not running: `{}`", moniker)]
SourceInstanceStopped { moniker: AbsoluteMoniker },
#[error(
"Instance identified as source of capability is a non-executable component: `{}`",
moniker
)]
SourceInstanceNotExecutable { moniker: AbsoluteMoniker },
#[error(
"Source for directory backing storage from `{}` must be a component or component manager's namespace, but was {}",
storage_moniker,
source_type
)]
StorageDirectorySourceInvalid { source_type: &'static str, storage_moniker: AbsoluteMoniker },
#[error(
"Source for directory storage from `{}` was a child `{}`, but this child was not found",
storage_moniker,
child_moniker
)]
StorageDirectorySourceChildNotFound {
storage_moniker: AbsoluteMoniker,
child_moniker: PartialMoniker,
},
#[error(
"A `storage` declaration with a backing directory from child `{}` was found at `{}` for \
`{}`, but no matching `expose` declaration was found in the child",
child_moniker,
moniker,
capability_id
)]
StorageFromChildExposeNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_id: String,
},
#[error(
"A `use from parent` declaration was found at `/` for `{}`, \
but no built-in capability matches",
capability_id
)]
UseFromComponentManagerNotFound { capability_id: String },
#[error(
"An `offer from parent` declaration was found at `/` for `{}`, \
but no built-in capability matches",
capability_id
)]
OfferFromComponentManagerNotFound { capability_id: String },
#[error(
"A `storage` declaration with a backing directory was found at `/` for `{}`, \
but no built-in capability matches",
capability_id
)]
StorageFromComponentManagerNotFound { capability_id: String },
#[error(
"A `use from parent` declaration was found at `{}` for `{}`, but no matching \
`offer` declaration was found in the parent",
moniker,
capability_id
)]
UseFromParentNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error(
"A `use` declaration was found at `{}` for {} `{}`, but no matching \
{} registration was found in the component's environment",
moniker,
capability_type,
capability_name,
capability_type
)]
UseFromEnvironmentNotFound {
moniker: AbsoluteMoniker,
capability_type: &'static str,
capability_name: CapabilityName,
},
#[error(
"A `use` declaration was found at `{}` for {} `{}`, and a corresponding \
entry was found in the root environment, which is not allowed.",
moniker,
capability_type,
capability_name
)]
UseFromRootEnvironmentNotAllowed {
moniker: AbsoluteMoniker,
capability_type: &'static str,
capability_name: CapabilityName,
},
#[error(
"An `environment` {} registration from `parent` was found at `{}` for `{}`, but no \
matching `offer` declaration was found in the parent",
capability_type,
moniker,
capability_name
)]
EnvironmentFromParentNotFound {
moniker: AbsoluteMoniker,
capability_type: &'static str,
capability_name: CapabilityName,
},
#[error(
"An `environment` {} registration from `#{}` was found at `{}` for `{}`, but no matching \
`expose` declaration was found in the child",
capability_type,
child_moniker,
moniker,
capability_name
)]
EnvironmentFromChildExposeNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_type: &'static str,
capability_name: CapabilityName,
},
#[error(
"An `environment` {} registration from `#{}` was found at `{}` for `{}`, but no matching \
child was found",
capability_type,
child_moniker,
moniker,
capability_name
)]
EnvironmentFromChildInstanceNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_name: CapabilityName,
capability_type: &'static str,
},
#[error(
"An `offer from parent` declaration was found at `{}` for `{}`, but no matching \
`offer` declaration was found in the parent",
moniker,
capability_id
)]
OfferFromParentNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error(
"A `storage` declaration with a backing directory from `parent` was found at `{}` for `{}`,
but no matching `offer` declaration was found in the parent",
moniker,
capability_id
)]
StorageFromParentNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error(
"An `offer from #{}` declaration was found at `{}` for `{}`, but no matching child was \
found",
child_moniker,
moniker,
capability_id
)]
OfferFromChildInstanceNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_id: String,
},
#[error(
"An `offer from #{}` declaration was found at `{}` for `{}`, but no matching collection \
was found",
collection,
moniker,
capability
)]
OfferFromCollectionNotFound {
collection: String,
moniker: AbsoluteMoniker,
capability: CapabilityName,
},
#[error(
"An `offer from #{}` declaration was found at `{}` for `{}`, but no matching `expose` \
declaration was found in the child",
child_moniker,
moniker,
capability_id
)]
OfferFromChildExposeNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_id: String,
},
// TODO: Could this be distinguished by use/offer/expose?
#[error(
"A framework capability was sourced to `{}` with id `{}`, but no such \
framework capability was found",
moniker,
capability_id
)]
CapabilityFromFrameworkNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error(
"A capability was sourced to a base capability `{}` from `{}`, but this is unsupported",
capability_id,
moniker
)]
CapabilityFromCapabilityNotFound { moniker: AbsoluteMoniker, capability_id: String },
// TODO: Could this be distinguished by use/offer/expose?
#[error(
"A capability was sourced to component manager with id `{}`, but no matching \
capability was found",
capability_id
)]
CapabilityFromComponentManagerNotFound { capability_id: String },
#[error(
"A capability was sourced to storage capability `{}` with id `{}`, but no matching \
capability was found",
storage_capability,
capability_id
)]
CapabilityFromStorageCapabilityNotFound { storage_capability: String, capability_id: String },
#[error(
"An exposed capability `{}` was used at `{}`, but no matching `expose` \
declaration was found",
capability_id,
moniker
)]
UsedExposeNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error(
"An `expose from #{}` declaration was found at `{}` for `{}`, but no matching child was \
found",
child_moniker,
moniker,
capability_id
)]
ExposeFromChildInstanceNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_id: String,
},
#[error(
"An `expose from #{}` declaration was found at `{}` for `{}`, but no matching collection \
was found",
collection,
moniker,
capability
)]
ExposeFromCollectionNotFound {
collection: String,
moniker: AbsoluteMoniker,
capability: CapabilityName,
},
#[error(
"An `expose from #{}` declaration was found at `{}` for `{}`, but no matching `expose` \
declaration was found in the child",
child_moniker,
moniker,
capability_id
)]
ExposeFromChildExposeNotFound {
child_moniker: PartialMoniker,
moniker: AbsoluteMoniker,
capability_id: String,
},
#[error(
"An `expose from framework` declaration was found at `{}` for `{}`, but no matching \
framework capability was found",
moniker,
capability_id
)]
ExposeFromFrameworkNotFound { moniker: AbsoluteMoniker, capability_id: String },
#[error("Routing a capability from an unsupported source type: {}", source_type)]
UnsupportedRouteSource { source_type: String },
#[error(transparent)]
ComponentInstanceError(#[from] ComponentInstanceError),
#[error(transparent)]
EventsRoutingError(#[from] EventsRoutingError),
#[error(transparent)]
RightsRoutingError(#[from] RightsRoutingError),
#[error(transparent)]
PolicyError(#[from] PolicyError),
}
impl RoutingError {
/// Convert this error into its approximate `fuchsia.component.Error` equivalent.
pub fn as_fidl_error(&self) -> fcomponent::Error {
fcomponent::Error::ResourceUnavailable
}
/// Convert this error into its approximate `zx::Status` equivalent.
pub fn as_zx_status(&self) -> zx::Status {
match self {
RoutingError::PolicyError(_) => zx::Status::ACCESS_DENIED,
_ => zx::Status::UNAVAILABLE,
}
}
pub fn source_instance_stopped(moniker: &AbsoluteMoniker) -> Self {
Self::SourceInstanceStopped { moniker: moniker.clone() }
}
pub fn source_instance_not_executable(moniker: &AbsoluteMoniker) -> Self {
Self::SourceInstanceNotExecutable { moniker: moniker.clone() }
}
pub fn storage_directory_source_invalid(
source_type: &'static str,
storage_moniker: &AbsoluteMoniker,
) -> Self {
Self::StorageDirectorySourceInvalid {
source_type,
storage_moniker: storage_moniker.clone(),
}
}
pub fn storage_directory_source_child_not_found(
storage_moniker: &AbsoluteMoniker,
child_moniker: &PartialMoniker,
) -> Self {
Self::StorageDirectorySourceChildNotFound {
storage_moniker: storage_moniker.clone(),
child_moniker: child_moniker.clone(),
}
}
pub fn storage_from_child_expose_not_found(
child_moniker: &PartialMoniker,
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::StorageFromChildExposeNotFound {
child_moniker: child_moniker.clone(),
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn use_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
Self::UseFromComponentManagerNotFound { capability_id: capability_id.into() }
}
pub fn offer_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
Self::OfferFromComponentManagerNotFound { capability_id: capability_id.into() }
}
pub fn storage_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
Self::StorageFromComponentManagerNotFound { capability_id: capability_id.into() }
}
pub fn use_from_parent_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::UseFromParentNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn offer_from_parent_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::OfferFromParentNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn storage_from_parent_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::StorageFromParentNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn offer_from_child_instance_not_found(
child_moniker: &PartialMoniker,
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::OfferFromChildInstanceNotFound {
child_moniker: child_moniker.clone(),
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn offer_from_child_expose_not_found(
child_moniker: &PartialMoniker,
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::OfferFromChildExposeNotFound {
child_moniker: child_moniker.clone(),
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn used_expose_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::UsedExposeNotFound { moniker: moniker.clone(), capability_id: capability_id.into() }
}
pub fn expose_from_child_instance_not_found(
child_moniker: &PartialMoniker,
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::ExposeFromChildInstanceNotFound {
child_moniker: child_moniker.clone(),
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn expose_from_child_expose_not_found(
child_moniker: &PartialMoniker,
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::ExposeFromChildExposeNotFound {
child_moniker: child_moniker.clone(),
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn capability_from_framework_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::CapabilityFromFrameworkNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn capability_from_capability_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::CapabilityFromCapabilityNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn capability_from_component_manager_not_found(capability_id: impl Into<String>) -> Self {
Self::CapabilityFromComponentManagerNotFound { capability_id: capability_id.into() }
}
pub fn capability_from_storage_capability_not_found(
storage_capability: impl Into<String>,
capability_id: impl Into<String>,
) -> Self {
Self::CapabilityFromStorageCapabilityNotFound {
storage_capability: storage_capability.into(),
capability_id: capability_id.into(),
}
}
pub fn expose_from_framework_not_found(
moniker: &AbsoluteMoniker,
capability_id: impl Into<String>,
) -> Self {
Self::ExposeFromFrameworkNotFound {
moniker: moniker.clone(),
capability_id: capability_id.into(),
}
}
pub fn unsupported_route_source(source: impl Into<String>) -> Self {
Self::UnsupportedRouteSource { source_type: source.into() }
}
}
/// Errors produced during routing specific to events.
#[derive(Error, Debug, Clone)]
pub enum EventsRoutingError {
#[error("Filter is not a subset")]
InvalidFilter,
#[error("Event routes must end at source with a filter declaration")]
MissingFilter,
#[error("Event mode, `{:?}`, cannot be propagated", event_mode)]
CannotPropagateEventMode { event_mode: EventMode },
#[error("Event routes must end at source with a modes declaration")]
MissingModes,
}
#[derive(Debug, Error, Clone)]
pub enum RightsRoutingError {
#[error("Requested rights greater than provided rights")]
Invalid,
#[error("Directory routes must end at source with a rights declaration")]
MissingRightsSource,
}
impl RightsRoutingError {
/// Convert this error into its approximate `zx::Status` equivalent.
pub fn as_zx_status(&self) -> zx::Status {
zx::Status::UNAVAILABLE
}
}