Package: octoploy
Kubernetes / openshift templating and deployment engineSimple python templating and deployment engine for openshift/k8 yml files. Detect changes made and only applies the
required objects.Use caseThis tool was born in the need to a simple templating system which can track changes (similar to terraform) but
with k8s object awareness.InstallationPython 3.8 or laterkubectlorocbinary in pathpip install octoployUsagegraph  TB
    root[Root folder<br>_root.yml]
    root --> app1[App 1<br>_index.yml<br>k8s yml files]
    root --> app2[App 2<br>_index.yml<br>k8s yml files]In octoploy you define apps, each app can contain multiple yml files. Additionally, there is a project configuration
which describes the k8 namespace.All yml files will be pre-processed before they will be imported. This includes replacing any known${KEY}variables
with their associate values and merging referenced templates.Deploy / PlanDeploys everythingoctoploy deploy-allDeploys all object of the app with the give nameoctoploy deploy nginxThe same commands are available forplan- which will list changes to be applied.octoploy plan / plan-allThis command executes theon-config-changetriggeroctoploy reload prometheusConfig structureconfigs
|- _root.yml <- Root config
|- my-app <- App
    |- _index.yml <- App config
    |- dc.yml <- Openshift/K8 yml file(s)
    |- secrets.yml < Encrypted secrets fileRoot configHere is a sample_root.ymlfile# Name of the namespace / openshift project
namespace: 'my-oc-project'

# K8s context which should be used for deploying
context: 'my-k8s-cluster-config'

# OPTIONAL STUFF
# Global variables
vars:
  DOMAIN: "dev-core.org"App configAn app is represented by a folder containing an_index.ymlfile and any additional openshift yml files. The following
shows all available parameters. Only the first 3 are required.# The type defines how the app will be used.
# Can be "app" (default) or "template"
type: 'app'

# Name of the deployment, available as variable, see below
name: 'my-app'

# Template which should be applied, none by default
applyTemplates: [ ]

# Templates which should be applied AFTER processing the other templates and base yml files
postApplyTemplates: [ ]

# Action which should be executed if a configmap has been changed
on-config-change:
  # Available options: 
  # deploy (re-deploys the deployment config - openshift specific)
  - deploy

  # exec (Executes a command inside the running container)
  - exec:
      command: /bin/sh
      args:
        - "-c"
        - "kill -HUP $(ps a | grep prometheus | grep -v grep | awk '{print $1}')"

# Additional variables which are used for replacements
vars:
  NSQ_NAME: 'nsq-core'

# Required parameters which must be passed to this app.
# This can be done via the CLI or if this app is a template the referring app can define it in "vars" 
params:
  - PASSWORD

# File based configmaps
configmaps:
  - name: nginx-config
    files:
      - file: "nginx.conf"ConfigmapsIn addition to the regular configmaps you can also define configmaps with a file source. This is done in
the_index.ymlfile:configmaps:
  - name: nginx-config
    files:
      - file: "nginx.conf"This will create a new configmap from the filenginx.confwith the namenginx-config. Any changes made to the file
will be automatically deployed.VariablesYou can refer to variables in yml files by using${VAR-NAME}. Variables can also be loaded from files (see loaders
below).# _index.yml
vars:
  # Regular key/value assignment
  key: valueIt is also possible to decorate objects using variables and merge them into other objects:# _index.yml
vars:
  someMerging:
    hello: world
    replicas: 2# dc.yml
spec:
  replicas: 1
  _merge: ${someMerging}Results in:spec:
  replicas: 2
  hello: worldGlobal variablesThe following variables are available anywhere inside the yml files by defaultKeyValueAPP_NAMEName of the app in the_index.ymlNAMESPACEName of the namespace in_root.ymlValue LoadersYou can load values from various sources using value loadersvars:
  # This will load the public/private and intermediate certs
  # from a pem file and store it in *_KEY, *_PUBLIC, *_CACERT
  # where * is the key of the value.
  # In this example: CERT_KEY, CERT_PUBLIC, CERT_CACERT
  CERT:
    loader: pem
    file: my-cert.pem

  # Load the content of a file into "MY_FILE"
  MY_FILE:
    loader: file
    file: someFile.bin
    # Optional: Defines in which encoding the file content should be read
    # utf-8 by default, only applicable if "conversion" is not set.
    encoding: utf-8

    # Optional: Conversion can be used to convert a binary file 
    # into a string representation, in this base base64 
    conversion: base64

  # Load the content of environment variables into ENV_*
  ENV:
    loader: envTemplatesYou can use templates to reuse and generate yml files. This might be useful when you want
to attach sidecar containers to multiple apps. To do so you create a new app with thetypefield set
totemplate. Other apps can now refer to this template via theapplyTemplatesorpostApplyTemplatesfield.
Templates can refer to other templates (recursively). Any vars defined are passed to the next template.classDiagram
    App <|-- Root: App receives global variables
    Template <|-- App: Template receives variables

    Template --|>App: Injects yml files into app
    class Root{
      +variables
    }
    class App{
      +parameters
      +k8s yml files
    }
    class Template{
      +parameters
      +k8s yml files
    }Example:|- some-template
    |- _index.yml
    |- dc.yml

|- my-app
    |- _index.yml <-- Referes to "some-template"
    |- others.ymlWill result in|- my-app
    |- _index.yml
    |- others.yml
    |- dc.ymlObject mergingThe template engine support content aware object merging. This allows you to decorate existing templates or enhance apps
with features. A common example would be a template which adds a monitoring sidecar container. In theexamplesyou can
find thensq-templatewhich defines a sidecar container.Here is a minimal example:# examples/nsq-template/dc.yml
kind: Deployment
apiVersion: apps/v1
spec:
  template:
    spec:
      containers:
        - name: "nsqd"
        image: "nsqio/nsq"# examples/my-app/dc.yml
kind: Deployment
apiVersion: apps/v1
metadata:
  name: "${APP_NAME}"

spec:
  replicas: 1
  selector:
    name: "${APP_NAME}"
  strategy:
    type: RollingUpdate

  template:
    metadata:
      labels:
        name: "${APP_NAME}"

    spec:
      containers:
        - name: "${APP_NAME}"
          image: "docker-registry.default.svc:5000/oc-project/my-app:prod"If we now apply the nsq-template to our app usingpostApplyTemplates: [nsq-template]theDeploymentConfigobject gets automatically merged:# Merged result after applying template
kind: Deployment
apiVersion: apps/v1
metadata:
  name: "${APP_NAME}"

spec:
  replicas: 1
  selector:
    name: "${APP_NAME}"
  strategy:
    type: RollingUpdate

  template:
    metadata:
      labels:
        name: "${APP_NAME}"

    spec:
      containers:
        - name: "${APP_NAME}"
          image: "docker-registry.default.svc:5000/oc-project/my-app:prod"
        # This is the part of the template
        - name: "nsqd"
          image: "nsqio/nsq"LoopsLoops allow you to apply the same template with different parameters. This is useful when deploying microservices which
all have the same openshift config.# _index.yml
applyTemplates: [ api-template ]
forEach:
  # NAME is required for each instance that should be created
  - NAME: entity-compare-api
    # You can define other vars as well
    PORT: 8080

  - NAME: favorite-api
    PORT: 8081LibraryIt's possible to define whole project as alibrary. This allows all apps and templates to be reused by another
project. An example would be the same setup for multiple systems which are separated by projects (e.g.dev/test/prod).# testLib/_root.yml
type: library

# Required parameters
params:
  - domain
  - dockerDomain
  - imageStreamTag# prod/_root.yml
namespace: 'prod-project'
inherit: testLib

# Required parameters
vars:
  domain: my-prod.dev-core.org
  dockerDomain: prod-docker.com
  imageStreamTag: prodWhen you now deploy theprodproject it will inherit all apps insidetestLib.SecretsYou can encrypt your k8s secrets usingexportOCTOPLOY_KEY="my password"octoployencryptsecrets.ymlThe file will be updated in place.For deploying encrypted secrets, you'll need to set the environment variableOCTOPLOY_KEYwith your key used to encrypt the data.State trackingOctoploy currently uses a ConfigMap calledoctoploy-stateto keep track of the object states.The ConfigMap contains  all managed objects and their md5 sum. If this hash has changed the whole object will be
applied. If the object does already exist, but is not listed in the state it will simply be added to the state.You can modify the name of the configmap by setting thestateNamevariable in the_root.ymlfile.Currently, the actual fields of the yml files are not compared, however this is a planned feature.ExamplesAll examples can be found in theexamplesfolder.ContributeThe code should be mostly commented. If you found a bug or want to improve something feel free to open an issue and
discuss your ideas.