Feat: envbinding support cloud resource deploy and share (#2734)

* Feat: envbinding support cloud resource deploy and bind

* Fix: change bind-cloud-resource to share-cloud-resource
This commit is contained in:
Somefive
2021-11-20 13:07:27 +08:00
committed by GitHub
parent b38aa1cdf0
commit 34aa74ff48
18 changed files with 911 additions and 26 deletions

View File

@@ -107,6 +107,10 @@ import (
#ApplyEnvBindApp: multicluster.#ApplyEnvBindApp
#DeployCloudResource: terraform.#DeployCloudResource
#ShareCloudResource: terraform.#ShareCloudResource
#LoadPolicies: oam.#LoadPolicies
#ListClusters: multicluster.#ListClusters

View File

@@ -68,35 +68,64 @@
...
}
#ApplyEnvBindApp: {
#do: "steps"
env: string
policy: string
app: string
namespace: string
#LoadEnvBindingEnv: #Steps & {
inputs: {
env: string
policy: string
}
loadPolicies: oam.#LoadPolicies @step(1)
loadPolicy: loadPolicies.value["\(policy)"]
policy_: string
if inputs.policy == "" {
envBindingPolicies: [ for k, v in loadPolicies.value if v.type == "env-binding" {k}]
policy_: envBindingPolicies[0]
}
if inputs.policy != "" {
policy_: inputs.policy
}
loadPolicy: loadPolicies.value["\(policy_)"]
envMap: {
for ev in loadPolicy.properties.envs {
"\(ev.name)": ev
}
...
}
envConfig: envMap["\(env)"]
envConfig_: envMap["\(inputs.env)"]
placementDecisions: multicluster.#MakePlacementDecisions & {
outputs: {
policy: policy_
envConfig: envConfig_
}
}
#PrepareEnvBinding: #Steps & {
inputs: {
env: string
policy: string
}
env_: inputs.env
policy_: inputs.policy
loadEnv: #LoadEnvBindingEnv & {
inputs: {
policyName: policy
envName: env
env: env_
policy: policy_
}
} @step(1)
envConfig: loadEnv.outputs.envConfig
placementDecisions: #MakePlacementDecisions & {
inputs: {
policyName: loadEnv.outputs.policy
envName: env_
placement: envConfig.placement
}
} @step(2)
patchedApp: multicluster.#PatchApplication & {
patchedApp: #PatchApplication & {
inputs: {
envName: env
envName: env_
if envConfig.selector != _|_ {
selector: envConfig.selector
}
@@ -106,10 +135,32 @@
}
} @step(3)
components: patchedApp.outputs.spec.components
apply: #Steps & {
for decision in placementDecisions.outputs.decisions {
for key, comp in components {
outputs: {
components: patchedApp.outputs.spec.components
decisions: placementDecisions.outputs.decisions
}
}
#ApplyEnvBindApp: {
#do: "steps"
env: string
policy: string
app: string
namespace: string
env_: env
policy_: policy
prepare: #PrepareEnvBinding & {
inputs: {
env: env_
policy: policy_
}
} @step(1)
apply: #Steps & {
for decision in prepare.outputs.decisions {
for key, comp in prepare.outputs.components {
"\(decision.cluster)-\(decision.namespace)-\(key)": #ApplyComponent & {
value: comp
if decision.cluster != _|_ {
@@ -118,7 +169,7 @@
if decision.namespace != _|_ {
namespace: decision.namespace
}
} @step(4)
} @step(2)
}
}
}

View File

@@ -0,0 +1,280 @@
#LoadTerraformComponents: {
#provider: "terraform"
#do: "load-terraform-components"
outputs: {
components: [...multicluster.#Component]
}
}
#GetConnectionStatus: {
#provider: "terraform"
#do: "get-connection-status"
inputs: {
componentName: string
}
outputs: {
healthy?: bool
}
}
#PrepareTerraformEnvBinding: #Steps & {
inputs: {
env: string
policy: string
}
env_: inputs.env
policy_: inputs.policy
prepare: multicluster.#PrepareEnvBinding & {
inputs: {
env: env_
policy: policy_
}
} @step(1)
loadTerraformComponents: #LoadTerraformComponents @step(2)
terraformComponentMap: {
for _, comp in loadTerraformComponents.outputs.components {
"\(comp.name)": comp
}
...
}
components_: [ for comp in prepare.outputs.components if terraformComponentMap["\(comp.name)"] != _|_ {comp}]
outputs: {
components: components_
decisions: prepare.outputs.decisions
}
}
#loadSecretInfo: {
component: {...}
appNamespace: string
name: string
namespace: string
env: string
if component.properties != _|_ && component.properties.writeConnectionSecretToRef != _|_ {
if component.properties.writeConnectionSecretToRef.name != _|_ {
name: component.properties.writeConnectionSecretToRef.name
}
if component.properties.writeConnectionSecretToRef.name == _|_ {
name: component.name
}
if component.properties.writeConnectionSecretToRef.namespace != _|_ {
namespace: component.properties.writeConnectionSecretToRef.namespace
}
if component.properties.writeConnectionSecretToRef.namespace == _|_ {
namespace: appNamespace
}
}
envName: "\(name)-\(env)"
}
#bindTerraformComponentToCluster: #Steps & {
comp: {...}
secret: {...}
env: string
decisions: [...{...}]
status: terraform.#GetConnectionStatus & {
inputs: componentName: "\(comp.name)-\(env)"
} @step(1)
read: kube.#Read & {
value: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: secret.envName
namespace: secret.namespace
...
}
...
}
} @step(2)
wait: {
#do: "wait"
continue: status.outputs.healthy && read.err == _|_
} @step(3)
sync: #Steps & {
for decision in decisions {
"\(decision.cluster)-\(decision.namespace)": kube.#Apply & {
cluster: decision.cluster
value: {
apiVersion: "v1"
kind: "Secret"
metadata: {
name: secret.name
if decision.namespace != _|_ && decision.namespace != "" {
namespace: decision.namespace
}
if decision.namespace == _|_ || decision.namespace == "" {
namespace: secret.namespace
}
...
}
type: "Opaque"
data: read.value.data
...
}
}
}
} @step(4)
}
#DeployCloudResource: {
#do: "steps"
env: string
name: string
policy: string
namespace: string
env_: env
policy_: policy
prepareDeploy: #PrepareTerraformEnvBinding & {
inputs: {
env: env_
policy: policy_
}
} @step(1)
deploy: #Steps & {
for comp in prepareDeploy.outputs.components {
"\(comp.name)": #Steps & {
secretMeta: #loadSecretInfo & {
component: comp
env: env_
appNamespace: namespace
}
apply: #ApplyComponent & {
value: {
name: "\(comp.name)-\(env)"
properties: {
writeConnectionSecretToRef: {
name: secretMeta.envName
namespace: secretMeta.namespace
}
if comp.properties != _|_ {
for k, v in comp.properties {
if k != "writeConnectionSecretToRef" {
"\(k)": v
}
}
}
...
}
for k, v in comp {
if k != "name" && k != "properties" {
"\(k)": v
}
}
...
}
} @step(1)
comp_: comp
bind: #bindTerraformComponentToCluster & {
comp: comp_
secret: secretMeta
env: env_
decisions: prepareDeploy.outputs.decisions
} @step(2)
secret: bind.read.value
update: kube.#Apply & {
value: {
metadata: {
for k, v in secret.metadata {
if k != "labels" {
"\(k)": v
}
}
labels: {
"app.oam.dev/name": name
"app.oam.dev/namespace": namespace
"app.oam.dev/component": comp.name
"app.oam.dev/env-name": env
"app.oam.dev/sync-alias": secretMeta.name
if secret.metadata.labels != _|_ {
for k, v in secret.metadata.labels {
if k != "app.oam.dev/name" && k != "app.oam.dev/sync-alias" && k != "app.oam.dev/env-name" {
"\(k)": v
}
}
}
...
}
}
for k, v in secret {
if k != "metadata" {
"\(k)": v
}
}
...
}
} @step(6)
}
}
...
} @step(2)
}
#ShareCloudResource: {
#do: "steps"
env: string
name: string
policy: string
namespace: string
namespace_: namespace
placements: [...multicluster.#PlacementDecision]
env_: env
policy_: policy
prepareBind: #PrepareTerraformEnvBinding & {
inputs: {
env: env_
policy: policy_
}
} @step(1)
decisions_: [ for placement in placements {
namespace: *"" | string
if placement.namespace != _|_ {
namespace: placement.namespace
}
if placement.namespace == _|_ {
namespace: namespace_
}
cluster: *"local" | string
if placement.cluster != _|_ {
cluster: placement.cluster
}
}]
deploy: #Steps & {
for comp in prepareBind.outputs.components {
"\(comp.name)": #Steps & {
secretMeta: #loadSecretInfo & {
component: comp
env: env_
appNamespace: namespace
}
comp_: comp
bind: #bindTerraformComponentToCluster & {
comp: comp_
secret: secretMeta
env: env_
decisions: decisions_
} @step(1)
}
}
} @step(2)
}