Skip to content

Commit

Permalink
fix(terraform): allow map outputs from modules
Browse files Browse the repository at this point in the history
Fixes #1947
  • Loading branch information
edvald authored and eysi09 committed Aug 5, 2020
1 parent f0c3001 commit ae06754
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 40 deletions.
21 changes: 7 additions & 14 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,8 @@ deployments:
# Latest error status message of the service (if any).
lastError:

# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:

# How many replicas of the service are currently running.
Expand Down Expand Up @@ -490,9 +489,8 @@ serviceStatuses:
# Latest error status message of the service (if any).
lastError:
# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:
# How many replicas of the service are currently running.
Expand Down Expand Up @@ -589,9 +587,8 @@ Examples:
# Latest error status message of the service (if any).
lastError:
# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:
# How many replicas of the service are currently running.
Expand Down Expand Up @@ -737,9 +734,8 @@ deployments:
# Latest error status message of the service (if any).
lastError:
# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:
# How many replicas of the service are currently running.
Expand Down Expand Up @@ -1438,9 +1434,8 @@ services:
# Latest error status message of the service (if any).
lastError:

# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:

# How many replicas of the service are currently running.
Expand Down Expand Up @@ -1965,9 +1960,8 @@ deployments:
# Latest error status message of the service (if any).
lastError:
# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:
# How many replicas of the service are currently running.
Expand Down Expand Up @@ -2482,9 +2476,8 @@ deployments:
# Latest error status message of the service (if any).
lastError:
# A map of primitive values, output from the service.
# A map of values output from the service.
outputs:
# Number, string or boolean
<name>:
# How many replicas of the service are currently running.
Expand Down
12 changes: 6 additions & 6 deletions docs/reference/module-types/terraform.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,13 +442,13 @@ Note that these are only resolved when deploying/running dependants of the servi

A map of all the outputs defined in the Terraform stack.

| Type |
| -------- |
| `object` |
| Type | Default |
| -------- | ------- |
| `object` | `{}` |

### `${runtime.services.<service-name>.outputs.<name>}`

| Type |
| ----- |
| `any` |
| Type |
| ------------------------------------------------ |
| `number | string | boolean | link | array[link]` |

2 changes: 1 addition & 1 deletion garden-service/src/config/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ export const joiVariables = () =>
.object()
.pattern(variableNameRegex, joi.alternatives(joiPrimitive(), joi.link("..."), joi.array().items(joi.link("..."))))
.default(() => ({}))
.unknown(false)
.unknown(true)
.description("Key/value map. " + joiVariablesDescription)

export const joiEnvVars = () =>
Expand Down
7 changes: 2 additions & 5 deletions garden-service/src/plugins/terraform/terraform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { pathExists } from "fs-extra"
import { createGardenPlugin } from "../../types/plugin/plugin"
import { getEnvironmentStatus, prepareEnvironment } from "./init"
import { providerConfigBaseSchema, ProviderConfig, Provider } from "../../config/provider"
import { joi } from "../../config/common"
import { joi, joiVariables } from "../../config/common"
import { dedent } from "../../util/string"
import { supportedVersions, defaultTerraformVersion, terraformCliSpecs } from "./cli"
import { ConfigureProviderParams, ConfigureProviderResult } from "../../types/plugin/provider/configureProvider"
Expand Down Expand Up @@ -88,10 +88,7 @@ export const gardenPlugin = createGardenPlugin({
See the [Terraform guide](${DOCS_BASE_URL}/advanced/terraform) for a high-level introduction to the \`terraform\` provider.
`,
serviceOutputsSchema: joi
.object()
.pattern(/.+/, joi.any())
.description("A map of all the outputs defined in the Terraform stack."),
serviceOutputsSchema: joiVariables().description("A map of all the outputs defined in the Terraform stack."),
schema,
handlers: {
suggestModules: async ({ name, path }: SuggestModulesParams): Promise<SuggestModulesResult> => {
Expand Down
7 changes: 2 additions & 5 deletions garden-service/src/types/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import normalizeUrl from "normalize-url"
import { format } from "url"
import { joiUserIdentifier, joi, joiIdentifier, joiArray, PrimitiveMap, joiPrimitive } from "../config/common"
import { joiUserIdentifier, joi, joiIdentifier, joiArray, PrimitiveMap, joiVariables } from "../config/common"
import { Module } from "./module"
import { ServiceConfig, serviceConfigSchema } from "../config/service"
import dedent = require("dedent")
Expand Down Expand Up @@ -229,10 +229,7 @@ export const serviceStatusSchema = () =>
.allow("")
.description("Latest status message of the service (if any)."),
lastError: joi.string().description("Latest error status message of the service (if any)."),
outputs: joi
.object()
.pattern(/.+/, joiPrimitive())
.description("A map of primitive values, output from the service."),
outputs: joiVariables().description("A map of values output from the service."),
runningReplicas: joi.number().description("How many replicas of the service are currently running."),
state: joi
.string()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,8 @@ output "test-file-path" {

output "my-output" {
value = "input: ${var.my-variable}"
}
}

output "map-output" {
value = map("first", "second")
}
2 changes: 1 addition & 1 deletion garden-service/test/unit/src/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -548,7 +548,7 @@ describe("ActionRouter", () => {
describe("deleteService", () => {
it("should correctly call the corresponding plugin handler", async () => {
const result = await actions.deleteService({ log, service, runtimeContext })
expect(result).to.eql({ forwardablePorts: [], state: "ready", detail: {} })
expect(result).to.eql({ forwardablePorts: [], state: "ready", detail: {}, outputs: {} })
})
})

Expand Down
14 changes: 7 additions & 7 deletions garden-service/test/unit/src/commands/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,10 @@ describe("DeleteEnvironmentCommand", () => {

expect(result!.providerStatuses["test-plugin"]["ready"]).to.be.false
expect(result!.serviceStatuses).to.eql({
"service-a": { forwardablePorts: [], state: "missing", detail: {} },
"service-b": { forwardablePorts: [], state: "missing", detail: {} },
"service-c": { forwardablePorts: [], state: "missing", detail: {} },
"service-d": { forwardablePorts: [], state: "missing", detail: {} },
"service-a": { forwardablePorts: [], state: "missing", detail: {}, outputs: {} },
"service-b": { forwardablePorts: [], state: "missing", detail: {}, outputs: {} },
"service-c": { forwardablePorts: [], state: "missing", detail: {}, outputs: {} },
"service-d": { forwardablePorts: [], state: "missing", detail: {}, outputs: {} },
})
expect(deletedServices.sort()).to.eql(["service-a", "service-b", "service-c", "service-d"])
})
Expand Down Expand Up @@ -212,7 +212,7 @@ describe("DeleteServiceCommand", () => {
expect(command.outputsSchema().validate(result).error).to.be.undefined

expect(result).to.eql({
"service-a": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {} },
"service-a": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {}, outputs: {} },
})
})

Expand All @@ -229,8 +229,8 @@ describe("DeleteServiceCommand", () => {
opts: withDefaultGlobalOpts({}),
})
expect(result).to.eql({
"service-a": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {} },
"service-b": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {} },
"service-a": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {}, outputs: {} },
"service-b": { forwardablePorts: [], state: "unknown", ingresses: [], detail: {}, outputs: {} },
})
})

Expand Down
4 changes: 4 additions & 0 deletions garden-service/test/unit/src/commands/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ describe("DeployCommand", () => {
durationMsec: 0,
error: undefined,
success: true,
outputs: {},
},
"service-d": {
version: "1",
Expand All @@ -183,6 +184,7 @@ describe("DeployCommand", () => {
durationMsec: 0,
error: undefined,
success: true,
outputs: {},
},
"service-a": {
version: "1",
Expand All @@ -193,6 +195,7 @@ describe("DeployCommand", () => {
durationMsec: 0,
error: undefined,
success: true,
outputs: {},
},
"service-b": {
version: "1",
Expand All @@ -203,6 +206,7 @@ describe("DeployCommand", () => {
durationMsec: 0,
error: undefined,
success: true,
outputs: {},
},
})

Expand Down
29 changes: 29 additions & 0 deletions garden-service/test/unit/src/plugins/terraform/terraform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { LogLevel } from "../../../../../src/logger/log-node"
import { ConfigGraph } from "../../../../../src/config-graph"
import { TerraformProvider } from "../../../../../src/plugins/terraform/terraform"
import { DeployTask } from "../../../../../src/tasks/deploy"
import { emptyRuntimeContext } from "../../../../../src/runtime-context"

describe("Terraform provider", () => {
const testRoot = getDataDir("test-projects", "terraform-provider")
Expand Down Expand Up @@ -257,6 +258,34 @@ describe("Terraform module type", () => {
expect(result["task.test-task"]!.output.log).to.equal("input: foo")
expect(result["task.test-task"]!.output.outputs.log).to.equal("input: foo")
})

it("should should return outputs with the service status", async () => {
const provider = await garden.resolveProvider(garden.log, "terraform")
const ctx = garden.getPluginContext(provider)
const applyCommand = findByName(terraformCommands, "apply-module")!
await applyCommand.handler({
ctx,
args: ["tf", "-auto-approve", "-input=false"],
log: garden.log,
modules: graph.getModules(),
})

const actions = await garden.getActionRouter()
const status = await actions.getServiceStatus({
service: graph.getService("tf"),
hotReload: false,
log: garden.log,
runtimeContext: emptyRuntimeContext,
})

expect(status.outputs).to.eql({
"map-output": {
first: "second",
},
"my-output": "input: foo",
"test-file-path": "./test.log",
})
})
})

context("autoApply=true", () => {
Expand Down

0 comments on commit ae06754

Please sign in to comment.