Skip to content

Commit

Permalink
fix: handle missing services gracefully in logs command
Browse files Browse the repository at this point in the history
Closes #207
  • Loading branch information
edvald committed Oct 26, 2018
1 parent 8ab5846 commit 3fcb73f
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 17 deletions.
13 changes: 10 additions & 3 deletions garden-service/src/commands/logs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,17 @@ export class LogsCommand extends Command<Args, Opts> {
}
})

// NOTE: This will work differently when we have Elasticsearch set up for logging, but is
// quite servicable for now.
await Bluebird.map(services, async (service: Service<any>) => {
await garden.actions.getServiceLogs({ service, stream, tail })
const status = await garden.actions.getServiceStatus({ service })
if (status.state === "ready" || status.state === "outdated") {
await garden.actions.getServiceLogs({ service, stream, tail })
} else {
await stream.write({
serviceName: service.name,
timestamp: new Date(),
msg: chalk.yellow(`<Service not running (state: ${status.state}). Please deploy the service and try again.>`),
})
}
})

return { result }
Expand Down
2 changes: 0 additions & 2 deletions garden-service/src/plugins/kubernetes/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,6 @@ export async function getServiceLogs(
void stream.write({ serviceName: service.name, timestamp, msg })
})

proc.stderr.pipe(process.stderr)

return new Promise<GetServiceLogsResult>((resolve, reject) => {
proc.on("error", reject)

Expand Down
6 changes: 3 additions & 3 deletions garden-service/src/plugins/kubernetes/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ export async function getContainerServiceStatus(

// FIXME: [objects, matched] and ingresses can be run in parallel
const objects = await createContainerObjects(ctx, service, runtimeContext, enableHotReload)
const matched = await compareDeployedObjects(ctx, objects)
const state = await compareDeployedObjects(ctx, objects)
const ingresses = await getIngresses(service, api)

return {
ingresses,
state: matched ? "ready" : "outdated",
version: matched ? version.versionString : undefined,
state,
version: state === "ready" ? version.versionString : undefined,
}
}

Expand Down
8 changes: 4 additions & 4 deletions garden-service/src/plugins/kubernetes/helm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,10 +314,10 @@ async function getServiceStatus(

// first check if the installed objects on the cluster match the current code
const objects = await getChartObjects(ctx, service, logEntry)
const matched = await compareDeployedObjects(ctx, objects)
let state = await compareDeployedObjects(ctx, objects)

if (!matched) {
return { state: "outdated" }
if (state !== "ready") {
return { state }
}

// then check if the rollout is complete
Expand All @@ -327,7 +327,7 @@ async function getServiceStatus(
const { ready } = await checkObjectStatus(api, namespace, objects)

// TODO: set state to "unhealthy" if any status is "unhealthy"
const state = ready ? "ready" : "deploying"
state = ready ? "ready" : "deploying"

return { state, version: version.versionString }
}
Expand Down
15 changes: 10 additions & 5 deletions garden-service/src/plugins/kubernetes/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -397,11 +397,14 @@ export async function waitForServices(
/**
* Check if each of the given Kubernetes objects matches what's installed in the cluster
*/
export async function compareDeployedObjects(ctx: PluginContext, objects: KubernetesObject[]): Promise<boolean> {
export async function compareDeployedObjects(ctx: PluginContext, objects: KubernetesObject[]): Promise<ServiceState> {
const existingObjects = await Bluebird.map(objects, obj => getDeployedObject(ctx, ctx.provider, obj))
let missing = true

for (let [obj, existingSpec] of zip(objects, existingObjects)) {
if (existingSpec && obj) {
missing = false

// the API version may implicitly change when deploying
existingSpec.apiVersion = obj.apiVersion

Expand Down Expand Up @@ -436,19 +439,21 @@ export async function compareDeployedObjects(ctx: PluginContext, objects: Kubern
obj = <KubernetesObject>removeNull(obj)
}

if (!existingSpec || !isSubset(existingSpec, obj)) {
if (existingSpec && !isSubset(existingSpec, obj)) {
// console.log(JSON.stringify(obj, null, 4))
// console.log(JSON.stringify(existingSpec, null, 4))
// console.log("----------------------------------------------------")
// throw new Error("bla")
return false
return "outdated"
}
}

return true
return missing ? "missing" : "ready"
}

async function getDeployedObject(ctx: PluginContext, provider: KubernetesProvider, obj: KubernetesObject) {
async function getDeployedObject(
ctx: PluginContext, provider: KubernetesProvider, obj: KubernetesObject,
): Promise<KubernetesObject | null> {
const api = new KubeApi(provider)
const namespace = obj.metadata.namespace || await getAppNamespace(ctx, provider)

Expand Down

0 comments on commit 3fcb73f

Please sign in to comment.