diff --git a/stdlib/gcp/gcloud.cue b/stdlib/gcp/gcloud.cue new file mode 100644 index 00000000..4a348991 --- /dev/null +++ b/stdlib/gcp/gcloud.cue @@ -0,0 +1,53 @@ +package gcp + +import ( + "dagger.io/dagger/op" + "dagger.io/alpine" +) + +// Re-usable gcloud component +#GCloud: { + config: #Config + version: string | *"288.0.0" + package: [string]: string + + #up: [ + op.#Load & { + from: alpine.#Image & { + "package": package + "package": bash: "=~5.1" + "package": python3: "=~3.8" + "package": jq: "=~1.6" + "package": curl: "=~7.76" + } + }, + + // Install the gcloud cli + op.#Exec & { + args: ["sh", "-c", + #""" + curl -sfL https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-sdk-\#(version)-linux-x86_64.tar.gz | tar -C /usr/local -zx + ln -s /usr/local/google-cloud-sdk/bin/gcloud /usr/local/bin + """#, + ] + }, + + // Setup auth + op.#WriteFile & { + dest: "/service_key" + content: config.serviceKey + }, + + op.#Exec & { + args: ["gcloud", "-q", "auth", "activate-service-account", "--key-file=/service_key"] + }, + + op.#Exec & { + args: ["gcloud", "-q", "config", "set", "project", config.project] + }, + + op.#Exec & { + args: ["gcloud", "-q", "config", "set", "compute/zone", config.region] + }, + ] +} diff --git a/stdlib/gcp/gcp.cue b/stdlib/gcp/gcp.cue new file mode 100644 index 00000000..797f5f16 --- /dev/null +++ b/stdlib/gcp/gcp.cue @@ -0,0 +1,15 @@ +package gcp + +import ( + "dagger.io/dagger" +) + +// Base Google Cloud Config +#Config: { + // GCP region + region: string + // GCP projcet + project: string + // GCP service key + serviceKey: dagger.#Secret +} diff --git a/stdlib/gcp/gke/gke.cue b/stdlib/gcp/gke/gke.cue new file mode 100644 index 00000000..89ba4641 --- /dev/null +++ b/stdlib/gcp/gke/gke.cue @@ -0,0 +1,84 @@ +package gke + +import ( + "dagger.io/dagger/op" + "dagger.io/gcp" +) + +// KubeConfig config outputs a valid kube-auth-config for kubectl client +#KubeConfig: { + // GCP Config + config: gcp.#Config + + // GKE cluster name + clusterName: string + + // Kubectl version + version: *"v1.19.9" | string + + // kubeconfig is the generated kube configuration file + kubeconfig: { + // FIXME There is a problem with dagger.#Secret type + string + + #up: [ + op.#Load & { + from: gcp.#GCloud & { + "config": config + } + }, + + op.#WriteFile & { + dest: "/entrypoint.sh" + content: #Code + }, + + op.#Exec & { + always: true + args: [ + "/bin/bash", + "--noprofile", + "--norc", + "-eo", + "pipefail", + "/entrypoint.sh", + ] + env: { + GKE_CLUSTER: clusterName + KUBECTL_VERSION: version + } + mount: "/cache/bin": "cache" + }, + op.#Export & { + source: "/kubeconfig" + format: "string" + }, + ] + } +} + +#Code: #""" + [ -e /cache/bin/kubectl ] || { + curl -sfL https://dl.k8s.io/${KUBECTL_VERSION}/bin/linux/amd64/kubectl -o /cache/bin/kubectl \ + && chmod +x /cache/bin/kubectl + } + + export KUBECONFIG=/kubeconfig + export PATH="$PATH:/cache/bin" + + # Generate a kube configiration + gcloud -q container clusters get-credentials "$GKE_CLUSTER" + + # Figure out the kubernetes username + CONTEXT="$(kubectl config current-context)" + USER="$(kubectl config view -o json | \ + jq -r ".contexts[] | select(.name==\"$CONTEXT\") | .context.user")" + + # Grab a kubernetes access token + ACCESS_TOKEN="$(gcloud -q config config-helper --format json --min-expiry 1h | \ + jq -r .credential.access_token)" + + # Remove the user config and replace it with the token + kubectl config unset "users.${USER}" + kubectl config set-credentials "$USER" --token "$ACCESS_TOKEN" + """# diff --git a/tests/stdlib.bats b/tests/stdlib.bats index f2a19e11..564135b2 100644 --- a/tests/stdlib.bats +++ b/tests/stdlib.bats @@ -42,24 +42,30 @@ setup() { "$DAGGER" compute "$TESTDIR"/stdlib/kubernetes/helm --input-dir kubeconfig=~/.kube --input-dir TestHelmSimpleChart.deploy.chartSource="$TESTDIR"/stdlib/kubernetes/helm/testdata/mychart } -@test "stdlib: s3" { +@test "stdlib: aws: s3" { skip_unless_secrets_available "$TESTDIR"/stdlib/aws/inputs.yaml "$DAGGER" compute "$TESTDIR"/stdlib/aws/s3 --input-dir TestDirectory="$TESTDIR"/stdlib/aws/s3/testdata --input-yaml "$TESTDIR"/stdlib/aws/inputs.yaml } -@test "stdlib: aws" { +@test "stdlib: aws: eks" { skip_unless_secrets_available "$TESTDIR"/stdlib/aws/inputs.yaml "$DAGGER" compute "$TESTDIR"/stdlib/aws/eks --input-yaml "$TESTDIR"/stdlib/aws/inputs.yaml } -@test "stdlib: ecr" { +@test "stdlib: aws: ecr" { skip_unless_secrets_available "$TESTDIR"/stdlib/aws/inputs.yaml "$DAGGER" compute "$TESTDIR"/stdlib/aws/ecr --input-yaml "$TESTDIR"/stdlib/aws/inputs.yaml } +@test "stdlib: gcp: gke" { + skip_unless_secrets_available "$TESTDIR"/stdlib/gcp/inputs.yaml + + "$DAGGER" compute "$TESTDIR"/stdlib/gcp/gke --input-yaml "$TESTDIR"/stdlib/gcp/inputs.yaml +} + @test "stdlib: docker-build" { "$DAGGER" compute "$TESTDIR"/stdlib/docker/build/ --input-dir source="$TESTDIR"/stdlib/docker/build } diff --git a/tests/stdlib/gcp/gke/gke.cue b/tests/stdlib/gcp/gke/gke.cue new file mode 100644 index 00000000..450f72d0 --- /dev/null +++ b/tests/stdlib/gcp/gke/gke.cue @@ -0,0 +1,32 @@ +package gke + +import ( + "dagger.io/gcp" + "dagger.io/gcp/gke" + "dagger.io/kubernetes" + "dagger.io/dagger/op" +) + +TestConfig: gcpConfig: gcp.#Config + +TestCluster: gke.#KubeConfig & { + config: TestConfig.gcpConfig + clusterName: "test-cluster" +} + +TestGKE: #up: [ + op.#Load & { + from: kubernetes.#Kubectl + }, + + op.#WriteFile & { + dest: "/kubeconfig" + content: TestCluster.kubeconfig + }, + + op.#Exec & { + always: true + args: ["kubectl", "get", "nodes"] + env: KUBECONFIG: "/kubeconfig" + }, +] diff --git a/tests/stdlib/gcp/inputs.yaml b/tests/stdlib/gcp/inputs.yaml new file mode 100644 index 00000000..3324a2cc --- /dev/null +++ b/tests/stdlib/gcp/inputs.yaml @@ -0,0 +1,36 @@ +TestConfig: + gcpConfig: + project: ENC[AES256_GCM,data:QVioZWWseno1,iv:WHdf8+4/rHg/NUug6GW4lFkJsUU4VhpE489myNTRnr4=,tag:7uUBSj6ncrfhmbtLNxURFA==,type:str] + serviceKey: ENC[AES256_GCM,data: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,iv:M1AGMV/mWY3h+7DuCegKDG14ooHvrylJ1IGhzfW4g+4=,tag:DaZ1Y0pPsYU8C2EkavVQrw==,type:str] + region: ENC[AES256_GCM,data:q77ffNChCAOCeA==,iv:01JZwKtBQd4hur8M6xvIul66FhN33ulHzRnFeQy3QIQ=,tag:asvkETPb1cnukzk6zusxfg==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: [] + lastmodified: "2021-05-19T23:31:38Z" + mac: ENC[AES256_GCM,data:7t/Jd78t/ExyLtg5B3J+8vPPxCc9UWa6QBBK0yQxKUIAVJ31loYeyOw1pULMpNRST2EQXZ899Ejdp3eZAHpx7gSc6Sg9Ep5Bcm0Hy1MJ1V07AYr+6y6KVyUToVcWQhzC0IV8ud9g8w/HAP3VY6yOGjgkKVcJXozliJZ1HrnWIww=,iv:K+Lz17H3OoN9symOQ8tF/iaov6pxxduI7cvfSS3WhIA=,tag:9sOzCGy0NiG5utWt+9wTZw==,type:str] + pgp: + - created_at: "2021-04-21T18:01:22Z" + enc: | + -----BEGIN PGP MESSAGE----- + + hQIMAzqVY590vudzAQ//Wl/GkApRyvWZnMPky8m/4O06NtJ9Zl4n8nXNCnWQ7gFL + Wt6y62u4mjIuIX5edRwbD726vF0MR84LxfAZ8ppw3lbnM+XDVeT12JA7VS33SOgU + oQBl4qTWrBEdVV2f83n56SvcF4YQkHjKcWWeSQZ2LGTj1jqt35trD/KzXQTwYaEi + 9JX9N+NYfAhuTDsSVi+mGeQnYZS4PAxkd9rWUcTm41EWh+d7hzNtz5T1Tx+a7q+S + XnHf6hxe9Q52Lsyumihi16eExz1Ym+x16gGtP5ioSZUiO45yk5/+iihUJJE6pBMF + Tss7KjLcoVREpl506e8Gsi5HEiMxlCR6KYzDOYfr6IWe3dPPhg9xJSJBIjF7JktQ + Bvua5y18bZIrlstIHeoe1Us5wEiLQigfNLBsoEN/aCwRr8o1KGnDuBasKssRUapL + xL4TxxQdlY6TJP/c8UVWN5q4l+Phsyt12d5KtugRRMSKDn66kRbvT4ykUy23cBO7 + XN1dQ+E9gyJRHCM2lPMeQsz9YlzHejJB4N+3aOlUeZH51hfVAGMuaSzjdPCHowyP + MYwg8wuasqSgNuc3sHj5J0WI1Ka14cE0O6jGlXDmviBSEyvRxovC/E/nyf80vF7n + BIG2DVJE0zYS4Ci0ebN79G0RhbxBWeF2EAPxiVbcFL0cDw8e6YcoyUiinwL1llPS + XgHZdvhkq3523wLn+XJUbc0xLK2EEZaQY9bEAeroX4fkyruCAZgxADH2JBnuO5Bc + aUBP1do4DxCBAzL3rT4uFFaiOCO5dKrliI9y6XTksRQm1nFo3SclN51SbFGlWxc= + =6cuG + -----END PGP MESSAGE----- + fp: 6CB37404020B5F0A0B41B5BB225EBAB0B936AC65 + unencrypted_suffix: _unencrypted + version: 3.7.1