Resource Graph Patterns

Pattern name

Resource Type

Propagate Id

Propagate Class

This example demonstrates how ID propagation through Resource References can be used to create a new instance of a resource for another resource. It involves provisioning a k8s-service-account resource for every workload resource provisioned.

How the example works

This example is made up of two Resource Definitions: one workload and two k8s-service-account Resource Definition. Both Resource Definitions use the humanitec/template driver.

A resource of type workload is automatically provisioned for each Workload in an Application in Humanitec. The workload will have the ID of modules.<workload id> and a class of default. This means that if an Application contains two workloads called workload-one and workload-two, two workload resources will be provisioned, one with ID modules.workload-one and the other with ID modules.workload-two.

The def-workload.yaml Resource Definition has a reference to a k8s-service-account resource. The Resource Reference does not specify either the class or the ID of the resource. This means that the k8s-service-account resource is provisioned with the same ID and class as the Workload.

Run the example

Prerequisites

See the prerequisites section in the README at the root of this repository.

In addition, the environment variable HUMANITEC_APP should be set to example-propagate-class.

Cost

This example will result in a single Pod being deployed to a Kubernetes Cluster.

Deploy the example

  1. Create a new Application:

    humctl create app "${HUMANITEC_APP}"
    
  2. Register the Resource Definitions:

    mkdir resource-definitions
    cp def-*.yaml ./resource-definitions
    humctl apply -f ./resource-definitions
    
  3. Deploy the Score Workload:

    humctl score deploy --org "${HUMANITEC_ORG}" --app "${HUMANITEC_APP}" --env "${HUMANITEC_ENV}" --token "${HUMANITEC_TOKEN}
    

Clean up the example

  1. Delete the Application

    humctl delete app "${HUMANITEC_APP}"
    
  2. Delete the Resource Definitions

    humctl delete -f ./resource-definitions
    rm -rf ./resource-definitions
    

score.yaml (view on GitHub) :

apiVersion: score.dev/v1b1

metadata:
  name: example-workload

containers:
  busybox:
    image: busybox:latest

    command:
      - /bin/sh
    args:
      - "-c"
      # This will output all of the environment variables in the container to
      # STDOUT every 15 seconds. This can be seen in the container logs in the
      # Humanitec UI.
      - "while true; do set; sleep 15; done"

Resource Definitions


def-k8s-service-account.yaml (view on GitHub) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: example-k8s-service-account
entity:
  criteria:
    - app_id: example-propagate-id
  driver_inputs:
    values:
      res_id: ${context.res.id}
      templates:
        init: |
          name: {{ .driver.values.res_id | splitList "." | last }}-sa
        outputs: |
          name: {{ .init.name }}
        manifests: |
          service-account.yaml:
            location: namespace
            data: |
              apiVersion: v1
              kind: ServiceAccount
              metadata:
                name: {{ .init.name }}

  driver_type: humanitec/template
  name: example-k8s-service-account
  type: k8s-service-account


def-workload.yaml (view on GitHub) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: example-workload
entity:
  criteria:
    - app_id: example-propagate-id
  driver_inputs:
    values:
      templates:
        outputs: |
          update: 
          - op: add
            path: /spec/serviceAccountName
            {{/*
              The resource reference does not specify ID or class so the ID and
              class of the workload being provisioned will be used.
            *//}
            value: ${resources.k8s-service-account.outputs.name}
  driver_type: humanitec/template
  name: example-workload
  type: workload


def-k8s-service-account.tf (view on GitHub) :

resource "humanitec_resource_definition" "example-k8s-service-account" {
  driver_type = "humanitec/template"
  id          = "example-k8s-service-account"
  name        = "example-k8s-service-account"
  type        = "k8s-service-account"
  driver_inputs = {
    values_string = jsonencode({
      "res_id" = "$${context.res.id}"
      "templates" = {
        "init"      = "name: {{ .driver.values.res_id | splitList \".\" | last }}-sa\n"
        "outputs"   = "name: {{ .init.name }}\n"
        "manifests" = <<END_OF_TEXT
service-account.yaml:
  location: namespace
  data: |
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: {{ .init.name }}
END_OF_TEXT
      }
    })
  }
}

resource "humanitec_resource_definition_criteria" "example-k8s-service-account_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.example-k8s-service-account.id
  app_id                 = "example-propagate-id"
}


def-workload.tf (view on GitHub) :

resource "humanitec_resource_definition" "example-workload" {
  driver_type = "humanitec/template"
  id          = "example-workload"
  name        = "example-workload"
  type        = "workload"
  driver_inputs = {
    values_string = jsonencode({
      "templates" = {
        "outputs" = <<END_OF_TEXT
update: 
- op: add
  path: /spec/serviceAccountName
  {{/*
    The resource reference does not specify ID or class so the ID and
    class of the workload being provisioned will be used.
  *//}
  value: $${resources.k8s-service-account.outputs.name}
END_OF_TEXT
      }
    })
  }
}

resource "humanitec_resource_definition_criteria" "example-workload_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.example-workload.id
  app_id                 = "example-propagate-id"
}

Top