-
Notifications
You must be signed in to change notification settings - Fork 3
Lifecycle
Hub CLI parameter hub.provides and HUB_PROVIDES env var exports a space-separated list of currently known provides.
When component declares requires - a list of capabilities that must be provided by prior components, platform stack, or environment - it became a list of hard requirements that must be satisfied before component (deploy) implementation is invoked. Failure to satisfy any requirement is hard error.
Component provides capabilities by declaring them in component's manifest provides list. Additionally, dynamic capabilities are collected from deploy output Provides: block, similar to Outputs:.
An aggregation of component's provides became (platform) stack provides.
A list of well known requires are built into Hub CLI. Such requirements could be sourced from environment, such as aws (a working AWS CLI). These requirements cannot be tuned.
A component might be declared optional on stack level
lifecycle:
optional:
- s3-bucket
Failure to deploy optional component is soft error. By default all components are mandatory. Those declared optional became optional. If mandatory components are specified, then everything else is optional.
lifecycle:
mandatory:
- kubernetes
- tiller
- traefik
A requirement could be softened by tuning it via lifecycle in stack manifest:
lifecycle:
requires:
optional:
- vault
- cdn:control-plane
- component.ingress.ssl.enabled:acm
vault and cdn are capabilities, control-plane and acm are component names. vault requirement is relaxed for all components, while cdn just for control-plane. Requirement became optional. acm is deployed only if ingress parameter component.ingress.ssl.enabled requests TLS-enabled stack (evaluates to truth-y value, ie. everything else besides false, "" empty string, 0, (unknown)).
When an optional requirement cannot be satisfied for a particular component, the component deployment (or undeployment) implementation is not invoked.
Requirements tuning of Base stack will be merged with tuning of derived stack. The following rules are used:
-
requirementsupersedes all priorrequirement:component- making requirement optional for everyone; -
requirement:componentsupersedes priorrequirement- making requirement optional forcomponent. There could be multiple declaration for different components; -
:erase all prior tuning; -
requirement:erase all prior tuning forrequirement; -
:componenterase all prior tuning forcomponent; - otherwise the entry is appended.
During elaborate Hub CLI creates a final manifest assembly that consists of:
- a leading document constructed from
hub.yaml,params*.yaml,fromStackYAML-s, adding parameters markedkind: userin*/hub-component.yaml; - all component's
hub-component.yamlwith the component name (meta.name) changed to matchhub.yamlspecified name.
Let's take Agile Stack's infra Dev stack as an example. The stack is built from:
-
agilestacks/hub.yaml- core infra; -
agilestacks/params.yaml- parameters for the infra; -
dev/hub.yaml- usesfromStack: agilestacksand adds some components: prometheus, etc.; -
dev/params.yaml- parameters for additional components; -
dev/params-dev.yaml- additional Dev stack parameters.
Separation between hub.yaml and params*.yaml is a convenience.
The files will be parsed and parameters will be arranged by hub elaborate in following order:
-
hub-component.yamlof allagilestackscomponents, in order ofcomponents: -
hub-component.yamlof alldevcomponents agilestacks/hub.yamlagilestacks/params.yamldev/hub.yamldev/params.yamldev/params-dev.yaml
hub-component.yaml kind: user parameters (1) are brought to the top level - first document of hub.yaml.elaborate with a component qualifier.
Parameters from (1), (2) to (7) are merged in the order specified:
-
kind: usertakes priority overkind: tech. -
value,default,fromEnv,env, andbriefare overwritten. - In case top-level parameter - ie. from
hub.yamlorparams*.yamlhas nocomponentqualifier, thenelaborateadditionally checks for all previously encountered parameters of the same name with a qualifier, then do merge into those. This is the reason for the following inhub.yaml.elaborate:
- name: component.auth-service.authApiSecret
kind: user
fromEnv: AUTH_API_SECRET
- name: component.auth-service.authApiSecret
component: auth-service
kind: user
fromEnv: AUTH_API_SECRETDuring deploy following things happens:
- Top-level parameters are locked:
-
kind: userparameters with no values are fetched fromfromEnv(if any) or asked on the terminal (if stdin is a TTY); -
defaultvalues are substituted; - expression evaluations are performed;
- cycles become errors;
- empty parameters become errors until suppressed with
empty: allow; - all errors and warning are collected and reported.
- If there is a state file, then parameters from state are loaded and merged into global state - but only empty (stack) values are replaced (by state values) and warnings are emitted.
- The locked set of top-level parameters are never changed after this step.
Top-level parameters can reference each other via expressions.
On each component deploy:
- Parameters are expanded:
- parameters with no values are searched in the top-level scope taking in account
componentanddependsqualifiers; - expression evaluations are performed;
- unknown empty parameters (without
value:expression) become errors until suppressed withempty: allowat which point their value assigned to empty string.
- Component parameters are never sent to top-level scope, but they are written into state file for informational purposes.
-
env:variables are set, then merged on top of OS environ to create process environment for component invocation. - Outputs are collected and put onto global outputs scope - with a qualifier - of the component producing the output
${component:parameter}. So that when parameters qualifiers are proceed, thename|qualifieris searched first and then just plainname. Outputs and parameters are processed independently although they looks very similar to the user. Outputs have higher precedence.
Component-level parameters may reference each other in expressions, top to bottom.
Set parameter value: " " or empty: allow to make empty parameter on hub-component.yaml level. During template processing and OS environment setup spaces are trimmed, effectively creating an empty substitution.
Capturing empty parameter from top-level scope does not require empty: allow on component level. But it might be useful to proceed with deployment when optional upstream component failed thus no outputs were produced.
© 2022 EPAM Systems, Inc. All Rights Reserved