Resource Graph Patterns

Pattern name

Resource Type

Delegator Resource

Delegator Resource

This example demonstrates how delegator Resource Definitions can be used to expose a shared base resource with different access policies.

How the example works

This example is made up of:

  • Two delegator s3 Resource Definitions
  • One base s3 Resource Definition
  • Two aws-policy Resource Definitions

and the resulting graph will look like:

flowchart LR
    WL_A[Workload A] -->|score resource dependency| DELEGATOR_RES_ADMIN(type: s3, id: shared.main-s3, class: admin)
    WL_B[Workload B] -->|score resource dependency| DELEGATOR_RES_READ_ONLY(type: s3, id: shared.main-s3, class: read-only)
    DELEGATOR_RES_ADMIN -->|co-provision| POL_ADMIN(type: aws-policy, id: shared.main-s3, class: s3-admin)
    DELEGATOR_RES_ADMIN -->|Resource Reference| BASE_RES(type: s3, id: shared.main-s3, class: concrete)
    DELEGATOR_RES_READ_ONLY -->|co-provision| POL_READ_ONLY(type: aws-policy, id: shared.main-s3, class: s3-read-only)
    DELEGATOR_RES_READ_ONLY -->|Resource Reference| BASE_RES

To keep the examples as simple as possible, the humanitec/echo driver is used throughout. Check out the Resource Packs if you are interested in examples with Resource Definitions that also include provisioning.

The s3 Resource Definition def-s3-concrete.yaml defines the underlying “base” resource and is matched as class: concrete.

In a real-world setup, this Resource Definition is the only one that would actually provision the s3 bucket using a Driver other than Echo, e.g. the Terraform Driver . The delegator resources will not actually provision anything. Their purpose is the co-provisioning of the appropriate aws-policy resource based on their class.

The aws-policy Resource Definitions def-aws-policy-s3-admin.yaml and def-aws-policy-s3-read-only.yaml contain the different policies we want to make available. Those are matched as admin and read-only.

The s3 Resource Definitions def-s3-admin.yaml and dev-s3-read-only.yaml are delegator resources that have two functions:

  • Co-provision the respective aws-policy Resource Definition.
  • Forward the outputs of the “base” resource using a Resource Reference .

When the workload defined in score-a.yaml now requests an s3 resource with class: admin, the Humanitec Platform Orchestrator creates the “delegator” s3 resource class: admin, the “base” s3 resource class: concrete, and co-provisions the aws-policy resource class: s3-admin.

Similar to the first workload, score-b.yaml requests an s3 resource, but this time with class: read-only and here the Humanitec Platform Orchestrator creates the “delegator” s3 resource class: read-only, the “base” s3 resource class: concrete, and co-provisions the aws-policy resource class: s3-read-only.

As both workloads used the same s3 resource id main-s3 via the id property on the resource objects in their Score files, they will use the same resource and thus the same underlying s3 bucket, but each workload uses a different access policy. The Score schema reference has details on this property.

Run the demo

Prerequisites

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

In addition, set these environment variables:

export HUMANITEC_APP=example-delegator
export HUMANITEC_ENV=development
export HUMANITEC_ORG=<your-org-id>

Cost

This example will result in a two Pods being deployed to a Kubernetes cluster.

Deploy the example

  1. Login to the Platform Orchestrator:

    humctl login
    
  2. Create a new app:

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

    mkdir resource-definitions
    cp def-*.yaml ./resource-definitions
    humctl apply -f ./resource-definitions
    
  4. Deploy the Score workload A:

    humctl score deploy --org "${HUMANITEC_ORG}" --app "${HUMANITEC_APP}" --env "${HUMANITEC_ENV}" --file score-a.yaml
    
  5. Deploy the Score workload B:

    humctl score deploy --org "${HUMANITEC_ORG}" --app "${HUMANITEC_APP}" --env "${HUMANITEC_ENV}" --file score-b.yaml
    
  6. Create the Resource Graph:

    humctl resources graph --org "${HUMANITEC_ORG}" --app "${HUMANITEC_APP}" --env "${HUMANITEC_ENV}" > graph.dot
    

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-a.yaml ( view on GitHub ) :

apiVersion: score.dev/v1b1
metadata:
  name: example-a

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"
    variables:
      BUCKET_NAME: ${resources.s3.bucket}

resources:
  s3:
    type: s3
    class: admin
    id: main-s3


score-b.yaml ( view on GitHub ) :

apiVersion: score.dev/v1b1
metadata:
  name: example-b

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"
    variables:
      BUCKET_NAME: ${resources.s3.bucket}

resources:
  s3:
    type: s3
    class: read-only
    id: main-s3

Resource Definitions


def-aws-policy-s3-admin.yaml ( view on GitHub ) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: aws-policy-s3-admin
entity:
  criteria:
    - app_id: example-delegator
      class: s3-admin
  driver_inputs:
    values:
      arn: arn:aws:iam::aws:policy/AmazonS3FullAccess
  # In a real-world scenario, a different Driver would be used for this resource, e.g. Terraform
  driver_type: humanitec/echo
  name: aws-policy-s3-admin
  type: aws-policy


def-aws-policy-s3-read-only.yaml ( view on GitHub ) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: aws-policy-s3-read-only
entity:
  criteria:
    - app_id: example-delegator
      class: s3-read-only
  driver_inputs:
    values:
      arn: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
  # In a real-world scenario, a different Driver would be used for this resource, e.g. Terraform
  driver_type: humanitec/echo
  name: aws-policy-s3-read-only
  type: aws-policy


def-s3-admin.yaml ( view on GitHub ) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: s3-admin
entity:
  criteria:
    - app_id: example-delegator
      class: admin
  driver_inputs:
    values:
      # This Resource reference to 's3.concrete' creates the dependency to the base resource
      bucket: ${resources['s3.concrete'].outputs.bucket}
  provision:
    # Co-provision a Resource of type "aws-policy" and class "s3-admin"
    aws-policy.s3-admin:
      is_dependent: false
      match_dependents: true
  driver_type: humanitec/echo
  name: s3-admin
  type: s3


def-s3-concrete.yaml ( view on GitHub ) :

# This Resource Definition represents the concrete base resource of the Delegator pattern
apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: s3-concrete
entity:
  criteria:
    - app_id: example-delegator
      class: concrete
  driver_inputs:
    values:
      bucket: example-bucket
  # In a real-world scenario, a different Driver would be used for the base resource, e.g. Terraform
  driver_type: humanitec/echo
  name: s3-concrete
  type: s3


def-s3-read-only.yaml ( view on GitHub ) :

apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: s3-read-only
entity:
  criteria:
    - app_id: example-delegator
      class: read-only
  driver_inputs:
    values:
      # This Resource reference to 's3.concrete' creates the dependency to the base resource
      bucket: ${resources['s3.concrete'].outputs.bucket}
  provision:
    # Co-provision a Resource of type "aws-policy" and class "s3-read-only"
    aws-policy.s3-read-only:
      is_dependent: false
      match_dependents: true
  driver_type: humanitec/echo
  name: s3-read-only
  type: s3


def-aws-policy-s3-admin.tf ( view on GitHub ) :

resource "humanitec_resource_definition" "aws-policy-s3-admin" {
  driver_type = "humanitec/echo"
  id          = "aws-policy-s3-admin"
  name        = "aws-policy-s3-admin"
  type        = "aws-policy"
  driver_inputs = {
    values_string = jsonencode({
      "arn" = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
    })
  }
}

resource "humanitec_resource_definition_criteria" "aws-policy-s3-admin_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.aws-policy-s3-admin.id
  app_id                 = "example-delegator"
  class                  = "s3-admin"
}


def-aws-policy-s3-read-only.tf ( view on GitHub ) :

resource "humanitec_resource_definition" "aws-policy-s3-read-only" {
  driver_type = "humanitec/echo"
  id          = "aws-policy-s3-read-only"
  name        = "aws-policy-s3-read-only"
  type        = "aws-policy"
  driver_inputs = {
    values_string = jsonencode({
      "arn" = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
    })
  }
}

resource "humanitec_resource_definition_criteria" "aws-policy-s3-read-only_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.aws-policy-s3-read-only.id
  app_id                 = "example-delegator"
  class                  = "s3-read-only"
}


def-s3-admin.tf ( view on GitHub ) :

resource "humanitec_resource_definition" "s3-admin" {
  driver_type = "humanitec/echo"
  id          = "s3-admin"
  name        = "s3-admin"
  type        = "s3"
  driver_inputs = {
    values_string = jsonencode({
      "bucket" = "$${resources['s3.concrete'].outputs.bucket}"
    })
  }

  provision = {
    "aws-policy.s3-admin" = {
      is_dependent     = false
      match_dependents = true
    }
  }
}

resource "humanitec_resource_definition_criteria" "s3-admin_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.s3-admin.id
  app_id                 = "example-delegator"
  class                  = "admin"
}


def-s3-concrete.tf ( view on GitHub ) :

resource "humanitec_resource_definition" "s3-concrete" {
  driver_type = "humanitec/echo"
  id          = "s3-concrete"
  name        = "s3-concrete"
  type        = "s3"
  driver_inputs = {
    values_string = jsonencode({
      "bucket" = "example-bucket"
    })
  }
}

resource "humanitec_resource_definition_criteria" "s3-concrete_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.s3-concrete.id
  app_id                 = "example-delegator"
  class                  = "concrete"
}


def-s3-read-only.tf ( view on GitHub ) :

resource "humanitec_resource_definition" "s3-read-only" {
  driver_type = "humanitec/echo"
  id          = "s3-read-only"
  name        = "s3-read-only"
  type        = "s3"
  driver_inputs = {
    values_string = jsonencode({
      "bucket" = "$${resources['s3.concrete'].outputs.bucket}"
    })
  }

  provision = {
    "aws-policy.s3-read-only" = {
      is_dependent     = false
      match_dependents = true
    }
  }
}

resource "humanitec_resource_definition_criteria" "s3-read-only_criteria_0" {
  resource_definition_id = resource.humanitec_resource_definition.s3-read-only.id
  app_id                 = "example-delegator"
  class                  = "read-only"
}

Top