Skip to content

Commit

Permalink
[BGS-153] User who provides APOLLO_GRAPH_REF should see a helpful m…
Browse files Browse the repository at this point in the history
…essage printed to stderr if the `whoami` call fails.
  • Loading branch information
monkpow committed Jan 21, 2025
1 parent bad1617 commit a4cfcc9
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 8 deletions.
13 changes: 10 additions & 3 deletions crates/rover-client/src/operations/subgraph/fetch_all/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,16 @@ where
inner
.call(GraphQLRequest::<SubgraphFetchAllQuery>::new(variables))
.await
.map_err(|err| RoverClientError::Service {
source: Box::new(err),
endpoint_kind: EndpointKind::ApolloStudio,
.map_err(|err| match err {
GraphQLServiceError::InvalidCredentials() => {
RoverClientError::PermissionError {
msg: "attempting to fetch subgraphs".to_string(),
}
}
_ => RoverClientError::Service {
source: Box::new(err),
endpoint_kind: EndpointKind::ApolloStudio,
},
})
.and_then(|response_data| {
get_subgraphs_from_response_data(req.graph_ref, response_data)
Expand Down
4 changes: 2 additions & 2 deletions crates/rover-graphql/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ http-body = { workspace = true }
http-body-util = { workspace = true }
rover-http = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
tower = { workspace = true }
url = { workspace = true }
Expand All @@ -22,8 +23,7 @@ url = { workspace = true }
anyhow = { workspace = true }
futures = { workspace = true }
rstest = { workspace = true }
serde = { workspace = true }
speculoos = { workspace = true }
tower-test = { workspace = true }
tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros"] }
tokio-test = { workspace = true }
tokio-test = { workspace = true }
57 changes: 54 additions & 3 deletions crates/rover-graphql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,49 @@ use graphql_client::GraphQLQuery;
use http::{uri::InvalidUri, HeaderValue, Method, StatusCode, Uri};
use http_body_util::Full;
use rover_http::{HttpRequest, HttpResponse};
use serde::{Deserialize, Serialize};
use tower::{Layer, Service};
use url::Url;

const JSON_CONTENT_TYPE: &str = "application/json";

#[derive(Serialize, Deserialize, Debug, Clone)]
struct PartialErrorInnerError {
message: String,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct PartialErrorInnerErrorList {
errors: Vec<PartialErrorInnerError>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct PartialErrorInnerBody {
body: PartialErrorInnerErrorList,
}

/// Re-export / renamed type alias for [`graphql_client::Response`]
pub type GraphQLResponse<T> = graphql_client::Response<T>;

/// Errors that may occur from using a [`GraphQLService`]
#[derive(thiserror::Error, Debug)]
pub enum GraphQLServiceError<T: Send + Sync + fmt::Debug> {
/// There was not data field provided in the response
/// There was no data field provided in the response
#[error("No data field provided")]
NoData(Vec<graphql_client::Error>),
/// The response returned some data, but there were errors
#[error("Data was returned, but with errors")]
#[error("Data was returned, but with errors: {}", friendly_errors_detail.join(" "))]
PartialError {
/// The partial data returned
data: T,
/// The GraphQL errors that were produced
errors: Vec<graphql_client::Error>,
/// display ready decoration of `errors`
friendly_errors_detail: Vec<String>,
},
/// The request failed to present credentials that authorize for the current request.
#[error("Invalid credentials provided. See \"Authenticating with GraphOS\" [https://www.apollographql.com/docs/rover/configuring].")]
InvalidCredentials(),
/// Data serialization error
#[error("Serialization error")]
Serialization(serde_json::Error),
Expand Down Expand Up @@ -189,7 +210,37 @@ where
})?;
if let Some(errors) = graphql_response.errors {
match graphql_response.data {
Some(data) => Err(GraphQLServiceError::PartialError { data, errors }),
Some(data) => {
let mut friendly_errors_detail: Vec<String> = vec![];
for err in errors.iter() {
let json_root =
err.extensions.as_ref().unwrap().get("response").unwrap();
friendly_errors_detail = serde_json::from_str::<PartialErrorInnerBody>(
&json_root.to_string(),
)
.unwrap()
.body
.errors
.iter()
.fold(vec![], |mut acc, x| {
acc.push(x.clone().message);
acc
});
}

if friendly_errors_detail
.join("")
.contains("Invalid credentials")
{
Err(GraphQLServiceError::InvalidCredentials {})
} else {
Err(GraphQLServiceError::PartialError {
data,
errors,
friendly_errors_detail,
})
}
}
None => Err(GraphQLServiceError::NoData(errors)),
}
} else {
Expand Down
1 change: 1 addition & 0 deletions src/composition/supergraph/config/resolver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ impl SupergraphConfigResolver<state::LoadRemoteSubgraphs> {
.map_err(|err| {
LoadRemoteSubgraphsError::FetchRemoteSubgraphsError(Box::new(err))
})?;

Ok(SupergraphConfigResolver {
state: state::LoadSupergraphConfig {
federation_version_resolver: self.state.federation_version_resolver,
Expand Down

0 comments on commit a4cfcc9

Please sign in to comment.