Specification

Resources

Provisioner

Dapr State Store


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.state-store.name}"
service:
  ports:
    tcp:
      port: 3000
      targetPort: 3000
resources:
  state-store:
    type: dapr-state-store


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

- uri: template://community-provisioners/redis-dapr-state-store
  type: dapr-state-store
  description: Generates a Dapr StateStore 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: state.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-redis-dapr-state-store.provisioners.yaml (view on GitHub) :

- uri: template://community-provisioners/redis
  type: dapr-state-store
  description: Generates a Dapr StateStore 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: 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 }}
    - apiVersion: dapr.io/v1alpha1
      kind: Component
      metadata:
        name: {{ .State.service }}
        {{ if ne .Namespace "" }}
        namespace: {{ .Namespace }}
        {{ end }}
      spec:
        type: state.redis
        version: v1
        metadata:
        - name: redisHost
          value: {{ .State.service }}:{{ .Init.port }}
        - name: redisPassword
          value: {{ .State.password }}    

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