From 20cc595833f5b0429a50cf86d6399be786cb40fa Mon Sep 17 00:00:00 2001 From: Ben Meier <1651305+astromechza@users.noreply.github.com> Date: Fri, 22 Nov 2024 13:50:14 +0000 Subject: [PATCH] feat: added an s3 default provisioner based on minio (#89) * feat: beginning of s3 provisioner with minio Signed-off-by: Ben Meier * feat: successfully running minio Signed-off-by: Ben Meier * fix: added bucket creation job Signed-off-by: Ben Meier * fix: ensure s3 job restarts Signed-off-by: Ben Meier * fix: incorrect file mode parsing bug Signed-off-by: Ben Meier --------- Signed-off-by: Ben Meier --- README.md | 1 + internal/convert/container_files.go | 2 +- .../default/zz-default.provisioners.yaml | 163 ++++++++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7eb7cc4..7980609 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ For details of how the standard "template" provisioner works, see the `template: | mongodb | default | (none) | `host`, `port`, `username`, `password`, `name`, `connection` | | ampq | default | (none) | `host`, `port`, `username`, `password`, `vhost` | | mssql | default | (none) | `server`, `port`, `database`, `password` | +| s3 | default | (none) | `endpoint`, `region`, `bucket`, `access_key_id`, `secret_key` | Users are encouraged to write their own custom provisioners to support new resource types or to modify the implementations above. diff --git a/internal/convert/container_files.go b/internal/convert/container_files.go index ac516c8..e5929e5 100644 --- a/internal/convert/container_files.go +++ b/internal/convert/container_files.go @@ -41,7 +41,7 @@ func convertContainerFile( var mountMode *int32 if fileElem.Mode != nil { - df, err := strconv.ParseInt(*fileElem.Mode, 10, 32) + df, err := strconv.ParseInt(*fileElem.Mode, 8, 32) if err != nil { return mount, nil, nil, errors.Wrapf(err, "mode: failed to parse '%s'", *fileElem.Mode) } diff --git a/internal/provisioners/default/zz-default.provisioners.yaml b/internal/provisioners/default/zz-default.provisioners.yaml index 5c5a93e..b40c428 100644 --- a/internal/provisioners/default/zz-default.provisioners.yaml +++ b/internal/provisioners/default/zz-default.provisioners.yaml @@ -915,3 +915,166 @@ ports: - port: 1433 targetPort: 1433 + +# This resource provides an in-cluster minio based S3 bucket with AWS-style credentials. +# This provides some common and well known outputs that can be used with any generic AWS s3 client. +# The outputs of the provisioner are a stateful set, a service, a secret, and a job per bucket. +- uri: template://default-provisioners/s3 + type: s3 + # The init template contains some initial seed data that can be used t needed. + init: | + sk: default-provisioners-minio-instance + state: | + bucket: {{ dig "bucket" (printf "bucket-%s" .Guid) .State | quote }} + shared: | + {{ .Init.sk }}: + instanceServiceName: {{ dig .Init.sk "instanceServiceName" (randAlpha 7 | lower | printf "minio-%s") .Shared | quote }} + instanceUsername: {{ dig .Init.sk "instanceUsername" (randAlpha 7 | printf "user-%s") .Shared | quote }} + instancePassword: {{ dig .Init.sk "instancePassword" (randAlphaNum 16) .Shared | quote }} + instanceAccessKeyId: {{ dig .Init.sk "instanceAccessKeyId" (randAlphaNum 20) .Shared | quote }} + instanceSecretKey: {{ dig .Init.sk "instanceSecretKey" (randAlphaNum 40) .Shared | quote }} + outputs: | + {{ $shared := dig .Init.sk (dict) .Shared }} + {{ $service := $shared.instanceServiceName }} + bucket: {{ .State.bucket }} + access_key_id: {{ $shared.instanceAccessKeyId | quote }} + secret_key: {{ encodeSecretRef $service "secret_key" }} + endpoint: http://{{ $service }}:9000 + region: "us-east-1" + # for compatibility with Humanitec's existing s3 resource + aws_access_key_id: {{ $shared.instanceAccessKeyId | quote }} + aws_secret_key: {{ encodeSecretRef $service "secret_key" }} + manifests: | + {{ $shared := dig .Init.sk (dict) .Shared }} + {{ $service := $shared.instanceServiceName }} + - apiVersion: apps/v1 + kind: StatefulSet + metadata: + name: {{ $service | quote }} + labels: + app.kubernetes.io/managed-by: score-k8s + app.kubernetes.io/name: {{ $service | quote }} + app.kubernetes.io/instance: {{ $service | quote }} + spec: + replicas: 1 + serviceName: {{ $service | quote }} + selector: + matchLabels: + app.kubernetes.io/instance: {{ $service | quote }} + template: + metadata: + labels: + app.kubernetes.io/managed-by: score-k8s + app.kubernetes.io/name: {{ $service | quote }} + app.kubernetes.io/instance: {{ $service | quote }} + spec: + automountServiceAccountToken: false + containers: + - name: minio + image: quay.io/minio/minio + args: ["server", "/data", "--console-address", ":9001"] + ports: + - name: service + containerPort: 9000 + - name: console + containerPort: 9001 + env: + - name: MINIO_ROOT_USER + value: {{ $shared.instanceUsername | quote }} + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ $service | quote }} + key: password + securityContext: + runAsUser: 1000 + runAsGroup: 1000 + allowPrivilegeEscalation: false + privileged: false + capabilities: + drop: + - ALL + volumeMounts: + - name: data + mountPath: /data + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + seccompProfile: + type: RuntimeDefault + volumeClaimTemplates: + - metadata: + name: data + labels: + app.kubernetes.io/managed-by: score-k8s + app.kubernetes.io/name: {{ $service | quote }} + app.kubernetes.io/instance: {{ $service | quote }} + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi + - apiVersion: v1 + kind: Secret + metadata: + name: {{ $service }} + labels: + app.kubernetes.io/managed-by: score-k8s + app.kubernetes.io/name: {{ $service }} + app.kubernetes.io/instance: {{ $service }} + data: + password: {{ $shared.instancePassword | b64enc }} + secret_key: {{ $shared.instanceSecretKey | b64enc }} + - apiVersion: v1 + kind: Service + metadata: + name: {{ $service }} + labels: + app.kubernetes.io/managed-by: score-k8s + app.kubernetes.io/name: {{ $service }} + app.kubernetes.io/instance: {{ $service }} + spec: + selector: + app.kubernetes.io/instance: {{ $service }} + type: ClusterIP + ports: + - name: service + port: 9000 + targetPort: 9000 + - name: console + port: 9001 + targetPort: 9001 + - apiVersion: batch/v1 + kind: Job + metadata: + name: {{ printf "%s-bucket-%s" $service .Guid }} + labels: + app.kubernetes.io/managed-by: score-k8s + spec: + template: + spec: + restartPolicy: OnFailure + containers: + - name: main + image: quay.io/minio/minio + command: + - /bin/bash + - -c + - | + set -eu + mc alias set myminio http://{{ $service }}:9000 {{ $shared.instanceUsername | quote }} $MINIO_ROOT_PASSWORD + mc admin user svcacct info myminio {{ $shared.instanceAccessKeyId | quote }} || mc admin user svcacct add myminio {{ $shared.instanceUsername | quote }} --access-key {{ $shared.instanceAccessKeyId | quote }} --secret-key $MINIO_SECRET_KEY + mc mb -p myminio/{{ .State.bucket }} + env: + - name: MINIO_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: {{ $service | quote }} + key: password + - name: MINIO_SECRET_KEY + valueFrom: + secretKeyRef: + name: {{ $service | quote }} + key: secret_key