components

The components key contains:

πŸ“˜

Please see the dedicated Components section of the documentation for details on each.


Components Composition

You can combine as many Components as you need in a single Environment, regardless of their kind.

Let's take an example:

  • payments-service to deploy a Helm Chart containing all what is needed for this microservice to run
  • checkout_proxy to deploy a Kubernetes manifest containing a simple proxy service
  • frontend-checkout to deploy a static application
  • admin-internal to deploy a monolith app which uses Docker-compose for local development
  • nginx to deploy the gateway of the Environment
  • mysql to deploy a Database
  • cloud-run-workers to deploy a batch processing job in any other place than Kubernetes
  • object-storage to create an S3 bucket to store compile reports
...
components:

  - kind: Helm
    name: payments-service
    ...

  - kind: KubernetesMafinest
    name: checkout-proxy
    ...

  - kind: StaticApplication
    name: frontend-checkout
    ...

  - kind: Application
    name: admin-internal
    ...
    
  - kind: Service
    name: nginx
    ...
    
  - kind: Database
    name: mysql
    ...
    
 	- kind: GenericComponent
    name: cloud-run-workers
    ...

    
 	- kind: Terraform
    name: object-storage
    ...

Schema for all Components

Some attributes are common for all Components, regardless of their kind. They are listed below.

πŸ“˜

More attributes are available, depending on the component kind. They will be detailed below.

components.[*]:

  kind:
    type: string
    required: true
    description: Type of the component

  name:
    type: string
    required: true
		description: Component name, used to reference the component internally; for Docker-compose Components, the name the Kubernetes services as well

  gitRepo:
    type: string
    required: false
    description: Git repository for the Component

  gitBranch: 
    type: string
    required: false
    description: Git branch / commit sha / tag for the Component

  gitApplicationPath: 
    type: string
    required: false
    description: Folder path within the Git repository; useful for monorepos

  version:
    type: string
    required: false
    description: Version used by the Bunnyshell parser for this component, default is "v1"
    
  hosts: 
    type: array
    required: false
    description: Specify the host URL (domain + path + service port (Kubernetes components)/external address).
    
  dependsOn:
    type: array
    required: false
    description: Specify the components which need to have the deploy / start workflows completed before starting the current's component deploy / start workflow.

kind

Available kinds:

  • Helm
  • KubernetesManifest
  • DockerImage
  • GenericComponent
  • Application
  • Service
  • Database
  • StaticApplication
  • InitContainer
  • SidecarContainer

Please read the specific Components documentation for details on each.

gitRepo

The gitRepo property in a YAML file serves as a reference to a Git repository. It allows you to define the URL of the repository where your source code is hosted. The format of the values should be in the https:// format for Git repositories. Additionally, if the git:// format is provided, it will be automatically converted to the https:// format for compatibility.

Depending on component type, the repository will either be:

  • for Helm, KubernetesManifest, Terraform and GenericComponents - cloned into the runner which is in charge of executing the deploy / destroy / start / stop workflows, so you can leverage files from within the repository in executing the workflows
  • for Docker-compose Components and DockerImage - used to build the image

For all Components, Bunnyshell will install a webhook so the Git Provider will notify Bunnyshell of the activity from within the repo. Currently, Pull Request create & close events are tracked, as well as commit pushes - for creating/destroying ephemerals, respectively updating Environments.

gitBranch

The branch for the Git repository. A commit sha or tag can also be specified.

gitApplicationPath

The path within the repository. Very important for detecting updates on applications in monorepos, as for a given Component, activity on other paths is ignored.

hosts

hosts:
  - hostname: 
        type: string
        required: true
        description: Hostname prefix, must be suffixed with "-${env.unique}.bunnyenv.com"
    path: 
        type: string
        required: false
        description: URL path, if any
    displayPaths:
        type: array
        required: false
        description: List of component public URLs (paths or full URL). Overrides the default (generated) list.
    servicePort:  
        type: string
        required: false
        description: "Public" port (not the container port), aka the one exposed through the Service definition
    public:
        type: boolean
        required: false
        description: Comes into effect when "security.allowedIps" is set. When set to "true" it allows traffic from all IPs, including those which do not exist in the allowedIps list.
    externalAddress:
    		type: string
        required: false
        description: Can be used to point the defined hostname to an external hostname (CNAME record). Incompatible with "servicePort", "public" or "selfManagedDns".
    selfManagedDns:
        type: boolean
        required: false
        description: Default to false. When set, the hostname can point to external domains to Bunnyshell. The DNS records for these hostnames will have to be managed by the user.
    k8s:
        type: hash
        required: false
        description: Configuration options for the generated Kubernetes resources

hosts[*].k8s

ingress:
    type: hash
    required: false
    description: Configuration options for the Kubernetes Ingress resource

hosts[*].k8s.ingress

className:
    type: string
    required: false
    description: The `ingressClassName` value for the Ingress resource. Defaults to "bns-nginx". use a blank string value for no-value. Supports interpolation. 
annotations:
    type: hash
    required: false
    description: Extra annotations for the Ingress resource. Supports interpolation for annotation values (not for keys). 

Examples

hosts:
  - hostname: backend-qmrxve.bunnyenv.com
    path: /
    servicePort: 8080
    public: true
hosts:
  - hostname: backend-qmrxve.bunnyenv.com
    externalAddress: foo.bar.example.com
    path: /
hosts:
  - hostname: stage-1.my-company.tld
    servicePort: 8080
    selfManagedDns: true
hosts:
  - hostname: stage-1.my-company.tld
    servicePort: 8080
    selfManagedDns: true
    k8s:
      ingress:
        className: my-own-ingress
        annotations:
            alb.ingress.kubernetes.io/scheme: internal
            alb.ingress.kubernetes.io/group.name: kube-system-internal
hosts:
  - hostname: backend-qmrxve.bunnyenv.com
    path: /
    servicePort: 8080
    displayPaths:
      - /admin
      - https://mycompany.tld/docs
hosts:
  - hostname: backend-qmrxve.bunnyenv.com
    path: /
    servicePort: 8080
    displayPaths: { }
# The "hostname" must match the targeted Ingress rule host ("*" matches anything).

hosts:
  - hostname: '*'
    displayPaths:
      - 'https://admin-{{ env.base_domain }}/admin'
  - hostname: 'admin-{{ env.base_domain }}'
    displayPaths:
      - '/'
  - hostname: '*-{{ env.base_domain }}'
    displayPaths:
      - '/'

You can use the hosts by injecting them into Environment Variables for other Components. Please see the Variable Interpolation dedicated page.

dependsOn

Specify a list of component names for which the current component must wait to finish their deploy/start jobs before starting its own deploy / start jobs.

dependsOn:
  - api
  - database

Schema for Docker-compose Components

πŸ“˜

Also see attributes for all components, as they apply for Docker-compose Components as well.

components.[*]:

  dockerCompose:
    type: hash
    required: true
    description: Contains information needed to build the image and run the component

  envVarMapping:
    type: hash
    required: true
    description: Supporting use of dynamic Env vars, such as Application / Service / Database URLs, generated by Bunnyshell; key-value pairs. Will be replaced with actual values before the deployment.

  pod:
    type: hash
    required: false
    description: Co-locate services on same pods and share folders between them (eg. programming language container + web server container, aka PHP-FPM + nginx).
      
  cronJobs:
    type: array
    required: false
    description: Configure cronJobs for this component

πŸ“˜

All schemas presented below are for the components.[*] path.

dockerCompose

All properties under this attribute are compatible with the compose specification.

Ultimately, they will be interpreted by the kompose.io converter when generating the Kubernetes manifests. Please consult the conversion support.

dockerCompose:
  build:
    context: 
      type: string
      required: true
      description: Path where the docker build will be ran
    dockerfile:
      type: string
      required: true
      description: Filename of the dockerfile, within the specified path (context)
    args:
      type: hash
      required: false
      description: Build arguments, expressed as key-value pairs
  environment:
    type: hash
    required: false
    description: Component-level variables. The SECRET[] method can be used to mark a secret value (e.g. "- VAR_NAME: SECRET['secret value']")
  deploy:
    resources:
      type: hash
      required: false
      description: Minimum and maximum resources a Component can utilize. Translates into requests and limits for Kubernetes.

Example

dockerCompose:
  build:
    context: .docker/php
    dockerfile: Dockerfile
    args:
      buildno: 1
  environment:
    ENV: production
    password: 'SECRET[mypassword]'
  deploy:
    resources:
      limits:
        cpus: 2
        memory: 10000M
      reservations:
        cpus: '0.50'
        memory: 5000M

pod

Allows to enhance the Pod specification with Kubernetes-native concepts: Init & Sidecar containers.

You would use Init Containers when handling initialization tasks, such as changing permissions on folders within a volume.
You would use Sidecar containers to group containers to run in a single Pod, in order to share files or use the same localhost.

pod:
  init_containers:
    type: array
    required: false
    description: The components of kind InitContainer that will run as an initContainer in this pod along with the main component
  sidecar_containers:
    type: array
    required: false
    description: The components of kind SidecarContainer that will run as an containers in this pod along with the main component

Example

Let's take an example which would use some volumes and mount them in the init and sidecar containers, respectively. shared_paths and volumes attributes on the pod.[*].init_container and pod.[*].sidecar_container will be explained separately.

The container init-fronted-custom-name will run before the actual container example is started.

The container sidecar-backend-custom-name will run alongside example, in the same Pod.

volumes:
  -
    name: node-modules-cache
    type: disk
    size: 1Gi
  -
    name: backend-sessions
    type: disk
    size: 1Gi
    
components:
  - name: example
    kind: Application
    ...
    pod:
      init_containers:
        -
          from: init-frontend
          name: init-fronted-custom-name
          environment:
              NODE_ENV: production
         shared_paths:
           -
             path: /opt/frontend/public
             target:
               path: /opt/nginx/public/static
               container: '@parent'
             initial_contents: '@self'
         volumes:
           -
             name: node-modules-cache
             mount: /opt/frontend/node_modules
      sidecar_containers:
        -
          from: sidecar-backend
          name: sidecar-backend-custom-name
          environment:
            COMPOSER_HOME: /opt/.composer
          shared_paths:
            -
              path: /opt/backend/.etc/nginx/config
              target:
                path: /etc/nginx/config
                container: '@parent'
              initial_contents: '@self'
          volumes:
            -
              name: backend-sessions
              mount: /opt/backend/sessions

pod.init_containers.[*]

name:
  type: string
  required: true
  description: The name of the container. Must be unique to be able to add several containers for the same Init/Sidecar type component.
from:
  type: string
  required: true
  description: The name of a component of kind InitContainer for init_containers or kind SidecarContainer for sidecar_containers.
environment:
  type: hash
  required: false
  description: A key-value map of environment variables to inject into this init container or sidecar container.
shared_paths:
  type: array
  required: false
  description: ReadWrite paths that should be shared between current init or sidecar container and a target container in the pod.
volumes:
  type: array
  required: false
  description: Volume mounts to be added to this init or sidecar container.

pod.init_containers.[*].shared_paths.[*]

shared_paths are Kubernetes emptyDir volumes, mounted between the init or sidecar container and another container within the Pod.

path:
  type: string
  required: true
  description: A path from the current init/sidecar container
target:
  type: hash
  required: true
  description: A target for path sharing
  keys:
    container:
      type: string
      required: true
      description: A container name in the same pod. Refer to the component where the pod is defined with '@parent'.
    path:
      type: string
      required: true
      description: A path in the defined target.container.
initial_contents:
  type: enum
  values: ['@self', '@target']
  required: true
  description: Shared path initial contents from either current init/sidecar container or target container.

pod.init_containers.[*].volumes.[*]

volumes are Kubernetes classic volume mounts.

name:
  type: string
  required: true
  description: The name of a volume, as defined in bunnyshell.yaml key "volumes".
mount:
  type: string
  required: true
  description: A path where the volume should be mounted in the current init/sidecar container.

pod.sidecar_containers.[*]

See pod.init_containers.[*], the definition is identical for sidecar and init containers.

pod.sidecar_containers.[*].shared_paths

See pod.init_containers.[*].shared_paths, the definition is identical for sidecar and init containers.

pod.sidecar_containers.[*].volumes.[*]

See pod.init_containers.[*].volumes.[*], the definition is identical for sidecar and init containers.

cronJobs

Allow configuring CronJobs for the component.

The Pod spawned by the CronJob will have the same spec as the Pod of the component, including Kubernetes resources and volumes.

The main component container will always be present, and additional containers can be included in the Pod from the sidecar / init containers.

Volumes can be excluded from the Pod. All volumes used in a CronJob must be network type.

The command is for the component's main container.

The schedule is the Kubernetes syntax for schedule.

CronJobs can be configured for Init- and SidecarContainers as well. This allows to configure a cron from a component that isn't always running in the cluster. When using the Init- or SidecarContainer in a component.pod the configured cronJobs are not carried over.

cronJobs:
  - 
    name: 
      type: string
      required: true
      description: The name of the CronJob Kubernetes resource which will be created
    schedule:
      type: string
      required: true
      description: Schedule syntax for the cron
    command:
      type: array
      required: true
      description: The command to run
    containers:
      type: array
      required: false
      description: If the component has also configured `.pod`, you can select the containers to be included in the cron Pod
    volumes:
      type: bool|array
      required: false
      description: If the component has also configured `.volumes`, you can select the volumes to be included in the cron Pod
    resources:
      type: hash
      required: false
      description: Minimum and maximum resources a Component can utilize. Translates into requests and limits for Kubernetes.
    executionTimeout:
      type: integer
      required: false
      description: Maximum execution time for the command, the Pod will be killed after this time.

Example

cronJobs:
  - name: nginx-test-no-vols
    schedule: '* */1 * * *'
    command:
      - /bin/sh
      - '-c'
      - 'nginx -t'
    containers:
      - nginx
    volumes: false # no volume included
    
  - name: nginx-test-all-vols-1
    schedule: '* */1 * * *'
    command:
      - /bin/sh
      - '-c'
      - 'nginx -t'
    containers:
      - nginx
    volumes: true # all volumes included
    
  - name: nginx-test-all-vols-2
    schedule: '* */1 * * *'
    command:
      - /bin/sh
      - '-c'
      - 'nginx -t'
    # all containers included by omitting the "containers" attribute
    # all volumes included
    
  - name: nginx-test-some-vols
    schedule: '* */1 * * *'
    command:
      - /bin/sh
      - '-c'
      - 'nginx -t'
    containers:
      - nginx
    volumes:
      - nginx-volume # some volumes included
    resources:
      limits:
        cpus: 2
        memory: 10000M
      reservations:
        cpus: '0.50'
        memory: 5000M
    executionTimeout: 120

Schema for Helm, KubernetesManifest and Terraform

πŸ“˜

Also see attributes for all components, as they apply for Helm, KubernetesManifest, GenericComponent Components as well.

components.[*]:

  environment:
      type: hash
      required: false
      description: A key-value map of component-level variables. The SECRET[] method can be used to mark a secret value (e.g. "- VAR_NAME: SECRET['secret value']")

  deploy:
      type: array
      required: false
      description: A list of commands that will be ran each time this environment is deployed.

  destroy:
      type: array
      required: false
      description: A list of commands that will be ran when this environment is deleted.

  start:
      type: array
      required: false
      description: A list of commands that will be ran each time this environment is started.

  stop:
      type: array
      required: false
      description: A list of commands that will be ran each time this environment is stopped.

  runnerImage:
      type: string
      required: false
      description: The Docker image in which the deploy/destroy/start/stop commands will be ran. 

  exportVariables:
      type: array
      required: false
      description: A list of variables that will be exported from the runner and will be made available to be used in interpolations as "components.NAME.exported.VAR_NAME".

runnerImage

The image which will be to run the specified scripts in. git* attributes, if specified, will also clone the repository and mount it in the running container.

deploy / destroy / start / stop

Sequence of scripts to be ran in each of the workflows. Please see the workflows documentation.

exportVariables

Environment Variables from the runner container which can be captured and stored in Bunnyshell, to be used by interpolating the value in later-ran Components.


Schema for DockerImage Components

πŸ“˜

Also see attributes for all components, as they apply for DockerImage Components as well, except hosts as this component won't run in a cluster, just builds an image.

components.[*]:

  context:
    type: string
    required: false
    description: Available path for build. Default value is "/".
    
  dockerfile:
    type: string
    required: false
    description: Path to Dockerfile, within the context. Default value is "Dockerfile".
    
  target:
    type: string
    required: false
    description: Specifies stage to be built.
    
  args:
    type: map
    required: false
    description: Key-value pairs for build arguments.

context

Same meaning as Docker context. Will make only the specified context available during the build.

Must be included in gitApplicationPath, otherwise the cloned part of the repo will not contain the context.

dockerfile

Same meaning as Docker dockerfile. Path to Dockerfile, within the context.

target

Same meaning as Docker `target`. Specifies the stage to be built.

args

Same meaning as Docker args. These are build arguments.


Schema for CustomDockerImage Components

πŸ“˜

Also see attributes for all components, as they apply for CustomDockerImage Components as well, except hosts as this component won't run in a cluster, just builds an image.

components.[*]:

  runnerImage:
    type: string
    required: true
    description: The Docker image in which the build commands will be ran.
    
  runnerImageAuth:
    type: hash
    required: false
    description: Credentials for pulling the runnerImage.
    
  environment:
    type: hash
    required: false
    description: A key-value map of omponent-level variables. The SECRET[] method can be used to mark a secret value (e.g. "- VAR_NAME: SECRET['secret value']")
    
  build:
    type: array
    required: true
    description: A list of commands that will be ran in order to build the Docker image.

runnerImage

The image which will be to run the specified scripts in. git* attributes will also clone the repository and mount it in the running container.

runnerImageAuth

Object with credentials for pulling the runnerImage. See examples for each provider in Custom Docker Image

runnerImageAuth:

  provider:
    type: string
    required: true
    description: The image registry type. One of: aws, aws_public, azure, docker_hub, gcp, github, gitlab, harbor, jfrog.
    
  username:
    type: string
    required: false
    description: Username for registry authentication.
    
  password:
    type: string
    required: true
    description: Password for registry authentication

build

Sequence of scripts to be ran in order to build the Docker image.


Schema for GenericComponent Components

Please see the Schema for Helm and KubernetesManifest, as the Generic Component inherits it all, with one difference.

runnerImage

The only difference is that, for GenericComponents you can use @self in case the commands should be ran inside the component built image.