add a gke + service account example
ADD
gcp-ts-gke-serviceaccount/Pulumi.yaml
+name: gcp-ts-gke-serviceaccount
+description: A Google Kubernetes Engine (GKE) + Service account example
+runtime: nodejs
+template:
+ config:
+ gcp:project:
+ description: The Google Cloud project to deploy into
+ gcp:zone:
+ description: The Google Cloud zone
+ gcp:credentials:
+ description: Your GCP Service Account key contents for GKE Administration
+ secret: true

ADD
gcp-ts-gke-serviceaccount/README.md
+[![Deploy](https://get.pulumi.com/new/button.svg)](https://app.pulumi.com/new)
+
+# Google Kubernetes Engine (GKE) Cluster with Service Account
+
+This example deploys an Google Cloud Platform (GCP) [Google Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/) cluster, and deploys an example application that consumes a PubSub topic. The cluster has a secret which contains [Google Cloud Service Account Credentials](https://cloud.google.com/iam/docs/service-accounts)
+
+## Deploying the App
+
+To deploy your infrastructure, follow the below steps.
+
+### Prerequisites
+
+1. [Install Pulumi](https://www.pulumi.com/docs/get-started/install/)
+1. [Install Node.js](https://nodejs.org/en/download/)
+1. Install a package manager for Node.js, such as [npm](https://www.npmjs.com/get-npm) or [Yarn](https://yarnpkg.com/en/docs/install).
+1. [Install Google Cloud SDK (`gcloud`)](https://cloud.google.com/sdk/docs/downloads-interactive)
+1. Configure GCP Auth
+
+ * Login using `gcloud`
+
+ ```bash
+ $ gcloud auth login
+ $ gcloud config set project <YOUR_GCP_PROJECT_HERE>
+ $ gcloud auth application-default login
+ ```
+ > Note: This auth mechanism is meant for inner loop developer
+ > workflows. If you want to run this example in an unattended service
+ > account setting, such as in CI/CD, please [follow instructions to
+ > configure your service account](https://www.pulumi.com/docs/intro/cloud-providers/gcp/setup/). The
+ > service account must have the role `Kubernetes Engine Admin` / `container.admin`.
+
+### Steps
+
+After cloning this repo, from this working directory, run these commands:
+
+1. Install the required Node.js packages:
+
+ This installs the dependent packages [needed](https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/) for our Pulumi program.
+
+ ```bash
+ $ npm install
+ ```
+
+1. Create a new Pulumi stack, which is an isolated deployment target for this example:
+
+ This will initialize the Pulumi program in TypeScript.
+
+ ```bash
+ $ pulumi stack init
+ ```
+
+1. Set the required GCP configuration variables:
+
+ This sets configuration options and default values for our cluster.
+
+ ```bash
+ $ pulumi config set gcp:project <YOUR_GCP_PROJECT_HERE>
+ $ pulumi config set gcp:zone us-west1-a // any valid GCP Zone here
+ ```
+
+1. Set some optional configuration variables (note, these values are optional and have defaults set):
+
+ ```bash
+ $ pulumi config set name <NAME>
+ $ pulumi config set machineType n1-standard-1
+ ```
+
+1. Stand up the GKE cluster:
+
+ To preview and deploy changes, run `pulumi update` and select "yes."
+
+ The `update` sub-command shows a preview of the resources that will be created
+ and prompts on whether to proceed with the deployment. Note that the stack
+ itself is counted as a resource, though it does not correspond
+ to a physical cloud resource.
+
+ You can also run `pulumi up --diff` to see and inspect the diffs of the
+ overall changes expected to take place.
+
+ Running `pulumi up` will deploy the GKE cluster. Note, provisioning a
+ new GKE cluster takes between 3-5 minutes.
+
+ ```bash
+
+ ```
+
+1. After 3-5 minutes, your cluster will be ready, and the kubeconfig YAML you'll use to connect to the cluster will
+ be available as an output.
+
+1. Access the Kubernetes Cluster using `kubectl`
+
+ To access your new Kubernetes cluster using `kubectl`, we need to setup the
+ `kubeconfig` file and download `kubectl`. We can leverage the Pulumi
+ stack output in the CLI, as Pulumi facilitates exporting these objects for us.
+
+ ```bash
+ $ pulumi stack output kubeconfig > kubeconfig
+ $ export KUBECONFIG=$PWD/kubeconfig
+ $ kubectl version
+ $ kubectl cluster-info
+ $ kubectl get nodes
+ ```
+
+1. Verify the pubsub example is working
+
+ The pubsub deployment should be running, you can check it by examining the logs:
+
+ ```bash
+ k logs -n pubsub -l appClass=pubsub
+ Pulling messages from Pub/Sub subscription...
+ ```
+
+1. Once you've finished, tear down your stack's resources by destroying and removing it:
+
+ ```bash
+ $ pulumi destroy --yes
+ $ pulumi stack rm --yes
+ ```
+

ADD
gcp-ts-gke-serviceaccount/index.ts
+// Copyright 2016-2019, Pulumi Corporation. All rights reserved.
+import * as gcp from "@pulumi/gcp";
+import * as k8s from "@pulumi/kubernetes";
+import * as pulumi from "@pulumi/pulumi";
+
+const config = new pulumi.Config();
+
+const name = config.get("name") ||
+ "gke-serviceaccount-example";
+export const masterVersion = config.get("masterVersion") ||
+ gcp.container.getEngineVersions().then(it => it.latestMasterVersion);
+const machineType = "n1-standard-1" || config.get("machineType")
+
+// Create a service account
+const serviceAccount = new gcp.serviceAccount.Account("serviceAccount", {
+ accountId: name,
+ displayName: "A service account for a GKE application",
+});
+
+const serviceAccountIAM = new gcp.projects.IAMBinding("serviceAccount-pub", {
+ role: "roles/pubsub.subscriber",
+ members: [pulumi.interpolate`serviceAccount:${serviceAccount.email}`]
+}, {parent: serviceAccount})
+
+const serviceAccountKey = new gcp.serviceAccount.Key("serviceAccount-key", {
+ serviceAccountId: serviceAccount.name,
+ publicKeyType: "TYPE_X509_PEM_FILE",
+}, {parent: serviceAccount, additionalSecretOutputs: ['privateKey']})
+
+// Create a GKE cluster
+const cluster = new gcp.container.Cluster(name, {
+ initialNodeCount: 2,
+ minMasterVersion: masterVersion,
+ nodeVersion: masterVersion,
+ nodeConfig: {
+ machineType: machineType,
+ oauthScopes: [
+ "https://www.googleapis.com/auth/compute",
+ "https://www.googleapis.com/auth/devstorage.read_only",
+ "https://www.googleapis.com/auth/logging.write",
+ "https://www.googleapis.com/auth/monitoring",
+ ],
+ },
+});
+
+// Export the Cluster name
+export const clusterName = cluster.name;
+
+// Manufacture a GKE-style kubeconfig. Note that this is slightly "different"
+// because of the way GKE requires gcloud to be in the picture for cluster
+// authentication (rather than using the client cert/key directly).
+export const kubeconfig = pulumi.all([cluster.name, cluster.endpoint, cluster.masterAuth]).apply(([name, endpoint, masterAuth]) => {
+ const context = `${gcp.config.project}_${gcp.config.zone}_${name}`;
+ return `apiVersion: v1
+clusters:
+- cluster:
+ certificate-authority-data: ${masterAuth.clusterCaCertificate}
+ server: https://${endpoint}
+ name: ${context}
+contexts:
+- context:
+ cluster: ${context}
+ user: ${context}
+ name: ${context}
+current-context: ${context}
+kind: Config
+preferences: {}
+users:
+- name: ${context}
+ user:
+ auth-provider:
+ config:
+ cmd-args: config config-helper --format=json
+ cmd-path: gcloud
+ expiry-key: '{.credential.token_expiry}'
+ token-key: '{.credential.access_token}'
+ name: gcp
+`;
+});
+
+// Create a Kubernetes provider instance that uses our cluster from above.
+const clusterProvider = new k8s.Provider(name, {
+ kubeconfig: kubeconfig,
+});
+
+const appLabels = {appClass: "pubsub"};
+
+// Create a Kubernetes Namespace
+const ns = new k8s.core.v1.Namespace("pubsub-ns", {
+ metadata: {
+ name: "pubsub",
+ labels: appLabels,
+ }
+}, {provider: clusterProvider});
+
+
+const gcpCredentials = new k8s.core.v1.Secret('gcp-credentials', {
+ metadata: {
+ namespace: ns.metadata.name,
+ labels: appLabels,
+ },
+ type: 'Opaque',
+ stringData: {
+ 'gcp-credentials.json': serviceAccountKey.privateKey.apply((x) => Buffer.from(x, 'base64').toString('utf8')),
+ },
+}, {provider: clusterProvider, parent: ns});
+
+const deployment = new k8s.apps.v1.Deployment("pubsub",
+ {
+ metadata: {
+ namespace: ns.metadata.name,
+ labels: appLabels,
+ },
+ spec: {
+ replicas: 1,
+ selector: {matchLabels: appLabels},
+ template: {
+ metadata: {
+ labels: appLabels,
+ },
+ spec: {
+ volumes: [
+ {
+ name: 'google-cloud-key',
+ secret: {
+ secretName: gcpCredentials.metadata.name,
+ }
+ }
+ ],
+ containers: [
+ {
+ name: "pubsub-example",
+ image: "gcr.io/google-samples/pubsub-sample:v1",
+ volumeMounts: [
+ {
+ name: "google-cloud-key",
+ mountPath: "/var/secrets/google"
+ }
+ ],
+ env: [{
+ name: "GOOGLE_APPLICATION_CREDENTIALS",
+ value: "/var/secrets/google/gcp-credentials.json"
+ }]
+ },
+ ],
+ },
+ },
+ },
+ },
+ {
+ provider: clusterProvider, parent: ns
+ },
+);

ADD
gcp-ts-gke-serviceaccount/package.json
+{
+ "name": "gke.typescript",
+ "devDependencies": {
+ "@types/node": "^10.0.0"
+ },
+ "dependencies": {
+ "@pulumi/gcp": "^3.0.0",
+ "@pulumi/kubernetes": "^2.4.0",
+ "@pulumi/pulumi": "^2.0.0"
+ }
+}

ADD
gcp-ts-gke-serviceaccount/tsconfig.json
+{
+ "compilerOptions": {
+ "strict": true,
+ "outDir": "bin",
+ "target": "es2016",
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "experimentalDecorators": true,
+ "pretty": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitReturns": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "index.ts"
+ ]
+}

add a gke + service account example