Specification

Resources

Provisioner

Dapr Pubsub


score.yaml (view on GitHub) :

apiVersion: score.dev/v1b1
metadata:
  name: my-workload
  annotations:
    dapr.io/enabled: "true"
    dapr.io/app-id: "my-workload"
    dapr.io/app-port: "3000"
containers:
  my-container:
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo $PUBSUB_NAME; echo '\n'; sleep 5; done"]
    variables:
      PUBSUB_NAME: "${resources.pubsub.name}"
service:
  ports:
    tcp:
      port: 3000
      targetPort: 3000
resources:
  pubsub:
    type: dapr-pubsub


10-redis-dapr-pubsub.provisioners.yaml (view on GitHub) :

- uri: template://community-provisioners/redis-dapr-pubsub
  type: dapr-pubsub
  description: Generates a Dapr PubSub Component pointing to a Redis Service.
  init: |
    port: 6379
    randomServiceName: redis-{{ randAlphaNum 6 }}
    randomPassword: {{ randAlphaNum 16 | quote }}    
  state: |
    serviceName: {{ dig "serviceName" .Init.randomServiceName .State | quote }}
    password: {{ dig "password" .Init.randomPassword .State | quote }}    
  outputs: |
    name: {{ .State.serviceName }}    
  expected_outputs:
    - name
  files: |
    components/{{ .State.serviceName }}.yaml: |
      apiVersion: dapr.io/v1alpha1
      kind: Component
      metadata:
        name: {{ .State.serviceName }}
      spec:
        type: pubsub.redis
        version: v1
        metadata:
        - name: redisHost
          value: {{ .State.serviceName }}:{{ .Init.port }}
        - name: redisPassword
          value: {{ .State.password }}
    {{ .State.serviceName }}/redis.conf: |
      requirepass {{ .State.password }}
      port {{ .Init.port }}
      save 60 1
      loglevel warning    
  volumes: |
    {{ .State.serviceName }}-data:
      name: {{ .State.serviceName }}-data
      driver: local
      labels:
        dev.score.compose.res.uid: {{ .Uid }}    
  services: |
    {{ .State.serviceName }}:
      labels:
        dev.score.compose.res.uid: {{ .Uid }}
      image: mirror.gcr.io/redis:7-alpine
      restart: always
      entrypoint: ["redis-server"]
      command: ["/usr/local/etc/redis/redis.conf"]
      volumes:
      - type: bind
        source: {{ .MountsDirectory }}/{{ .State.serviceName }}/redis.conf
        target: /usr/local/etc/redis/redis.conf
        read_only: true
      - type: volume
        source: {{ .State.serviceName }}-data
        target: /data
        volume:
          nocopy: true    
  info_logs: |
    - "{{.Uid}}: To connect to redis: \"docker run -it --network {{ .ComposeProjectName }}_default --rm redis redis-cli -h {{ .State.serviceName | squote }} -a {{ .State.password | squote }}\""    

Initialize your local workspace, by importing a specific community provisioner:

score-commpose init --provisioners REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml

Note: you need to replace REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml by the actual provisioner file you want to use and import. More information here.

Get the provisioners definition:

score-compose provisioners list

Generate the platform specific manifests:

score-commpose generate score.yaml

See the resource outputs:

score-commpose resources list

You can run the following command on each resource listed with the previous command to get their outputs:

score-commpose resources get-outputs

Deploy the generated manifests:

docker compose up -d

See the running containers:

docker ps


10-rabbitmq-dapr-pubsub.provisioners.yaml (view on GitHub) :

- uri: template://community-provisioners/rabbitmq-dapr-pubsub
  type: dapr-pubsub
  description: Generates a Dapr PubSub Component pointing to a RabbitMQ StatefulSet.
  init: |
    port: 5672
    managementPort: 15672    
  state: |
    service: rabbitmq-{{ .SourceWorkload }}-{{ substr 0 8 .Guid | lower }}    
  outputs: |
    name: {{ .State.service }}    
  expected_outputs:
    - name
  manifests: |
    - apiVersion: dapr.io/v1alpha1
      kind: Component
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
      spec:
        type: pubsub.rabbitmq
        version: v1
        metadata:
        - name: host
          value: "amqp://{{ .State.service }}:{{ .Init.port }}"
    - apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
        annotations:
          k8s.score.dev/source-workload: {{ .SourceWorkload }}
          k8s.score.dev/resource-uid: {{ .Uid }}
          k8s.score.dev/resource-guid: {{ .Guid }}
        labels:
          app.kubernetes.io/managed-by: score-k8s
          app.kubernetes.io/name: {{ .State.service }}
          app.kubernetes.io/instance: {{ .State.service }}
      spec:
        serviceName: {{ .State.service }}
        replicas: 1
        selector:
          matchLabels:
            app.kubernetes.io/instance: {{ .State.service }}
        template:
          metadata:
            labels:
              app.kubernetes.io/managed-by: score-k8s
              app.kubernetes.io/name: {{ .State.service }}
              app.kubernetes.io/instance: {{ .State.service }}
          spec:
            containers:
              - name: rabbitmq
                image: mirror.gcr.io/rabbitmq:3-management-alpine
                ports:
                  - name: amqp
                    containerPort: {{ .Init.port }}
                  - name: management
                    containerPort: {{ .Init.managementPort }}
                volumeMounts:
                  - name: data
                    mountPath: /var/lib/rabbitmq
                readinessProbe:
                  exec:
                    command:
                      - rabbitmq-diagnostics
                      - -q
                      - check_port_connectivity
                  periodSeconds: 3
                  initialDelaySeconds: 30
                  timeoutSeconds: 5
        volumeClaimTemplates:
          - metadata:
              name: data
            spec:
              accessModes: ["ReadWriteOnce"]
              resources:
                requests:
                  storage: 3Gi
    - apiVersion: v1
      kind: Service
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
        annotations:
          k8s.score.dev/source-workload: {{ .SourceWorkload }}
          k8s.score.dev/resource-uid: {{ .Uid }}
          k8s.score.dev/resource-guid: {{ .Guid }}
        labels:
          app.kubernetes.io/managed-by: score-k8s
          app.kubernetes.io/name: {{ .State.service }}
          app.kubernetes.io/instance: {{ .State.service }}
      spec:
        ports:
          - port: {{ .Init.port }}
            targetPort: {{ .Init.port }}
            name: amqp
          - port: {{ .Init.managementPort }}
            targetPort: {{ .Init.managementPort }}
            name: management
        selector:
          app.kubernetes.io/instance: {{ .State.service }}
        type: ClusterIP    

10-redis-dapr-pubsub.provisioners.yaml (view on GitHub) :

- uri: template://community-provisioners/redis-dapr-pubsub
  type: dapr-pubsub
  description: Generates a Dapr PubSub Component pointing to a Redis StatefulSet.
  init: |
    randomPassword: {{ randAlphaNum 16 | quote }}
    port: 6379    
  state: |
    service: redis-{{ .SourceWorkload }}-{{ substr 0 8 .Guid | lower }}
    username: default
    password: {{ dig "password" .Init.randomPassword .State | quote }}    
  outputs: |
    name: {{ .State.service }}    
  expected_outputs:
    - name
  manifests: |
    - apiVersion: dapr.io/v1alpha1
      kind: Component
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
      spec:
        type: pubsub.redis
        version: v1
        metadata:
        - name: redisHost
          value: {{ .State.service }}:{{ .Init.port }}
        - name: redisPassword
          value: {{ .State.password }}
    - apiVersion: v1
      kind: Secret
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
        annotations:
          k8s.score.dev/source-workload: {{ .SourceWorkload }}
          k8s.score.dev/resource-uid: {{ .Uid }}
          k8s.score.dev/resource-guid: {{ .Guid }}
        labels:
          app.kubernetes.io/managed-by: score-k8s
          app.kubernetes.io/name: {{ .State.service }}
          app.kubernetes.io/instance: {{ .State.service }}
      data:
        password: {{ .State.password | b64enc }}
        redis.conf: {{ printf "requirepass %s\nport 6379\nsave 60 1\nloglevel warning\n" .State.password | b64enc }}
    - apiVersion: apps/v1
      kind: StatefulSet
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
        annotations:
          k8s.score.dev/source-workload: {{ .SourceWorkload }}
          k8s.score.dev/resource-uid: {{ .Uid }}
          k8s.score.dev/resource-guid: {{ .Guid }}
        labels:
          app.kubernetes.io/managed-by: score-k8s
          app.kubernetes.io/name: {{ .State.service }}
          app.kubernetes.io/instance: {{ .State.service }}
      spec:
        replicas: 1
        serviceName: {{ .State.service }}
        selector:
          matchLabels:
            app.kubernetes.io/instance: {{ .State.service }}
        template:
          metadata:
            labels:
              app.kubernetes.io/managed-by: score-k8s
              app.kubernetes.io/name: {{ .State.service }}
              app.kubernetes.io/instance: {{ .State.service }}
            annotations:
              k8s.score.dev/source-workload: {{ .SourceWorkload }}
              k8s.score.dev/resource-uid: {{ .Uid }}
              k8s.score.dev/resource-guid: {{ .Guid }}
          spec:
            automountServiceAccountToken: false
            containers:
            - name: redis
              image: mirror.gcr.io/redis:7-alpine
              securityContext:
                allowPrivilegeEscalation: false
                capabilities:
                  drop:
                    - ALL
                privileged: false
                readOnlyRootFilesystem: true
              ports:
              - name: redis
                containerPort: {{ .Init.port }}
              volumeMounts:
              - name: redis-data
                mountPath: /data
              - name: config
                mountPath: /usr/local/etc/redis
              readinessProbe:
                exec:
                  command:
                  - redis-cli
                  - ping
                periodSeconds: 3
            securityContext:
              fsGroup: 1000
              runAsGroup: 1000
              runAsNonRoot: true
              runAsUser: 1000
              seccompProfile:
                type: RuntimeDefault
            volumes:
            - name: config
              secret:
                secretName: {{ .State.service }}
                items:
                - key: redis.conf
                  path: redis.conf
        volumeClaimTemplates:
        - metadata:
            name: redis-data
            annotations:
              k8s.score.dev/source-workload: {{ .SourceWorkload }}
              k8s.score.dev/resource-uid: {{ .Uid }}
              k8s.score.dev/resource-guid: {{ .Guid }}
            labels:
              app.kubernetes.io/managed-by: score-k8s
              app.kubernetes.io/name: {{ .State.service }}
              app.kubernetes.io/instance: {{ .State.service }}
          spec:
            accessModes: ["ReadWriteOnce"]
            resources:
              requests:
                storage: 1Gi
    - apiVersion: v1
      kind: Service
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
        annotations:
          k8s.score.dev/source-workload: {{ .SourceWorkload }}
          k8s.score.dev/resource-uid: {{ .Uid }}
          k8s.score.dev/resource-guid: {{ .Guid }}
        labels:
          app.kubernetes.io/managed-by: score-k8s
          app.kubernetes.io/name: {{ .State.service }}
          app.kubernetes.io/instance: {{ .State.service }}
      spec:
        selector:
          app.kubernetes.io/instance: {{ .State.service }}
        type: ClusterIP
        ports:
        - port: {{ .Init.port }}
          targetPort: {{ .Init.port }}    

Initialize your local workspace, by importing a specific community provisioner:

score-k8s init --provisioners REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml

Note: you need to replace REPLACE-ME-WITH-ACTUAL-PROVISIONER-FILE-URL.yaml by the actual provisioner file you want to use and import. More information here.

Get the provisioners definition:

score-k8s provisioners list

Generate the platform specific manifests:

score-k8s generate score.yaml

See the resource outputs:

score-k8s resources list

You can run the following command on each resource listed with the previous command to get their outputs:

score-k8s resources get-outputs

Deploy the generated manifests:

kubectl apply -f manifests.yaml

See the running containers:

kubectl get all