gcp(gke): add GKE + Kubernetes Hello World
ADD
gcp-ts-gke-hello-world/Pulumi.yaml
+name: gcp-ts-gke-hello-world
+description: A Google Kubernetes Engine (GKE) + Kubernetes Hello World 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-hello-world/config.ts
+// Copyright 2016-2019, Pulumi Corporation. All rights reserved.
+import * as pulumi from "@pulumi/pulumi";
+import { Config } from "@pulumi/pulumi";
+
+const config = new Config();
+
+export const clusterConfig = {
+ // nodeCount is the number of cluster nodes to provision. Defaults to 2 if unspecified.
+ nodeCount: config.getNumber("nodeCount") || 2,
+
+ // nodeMachineType is the machine type to use for cluster nodes. Defaults to n1-standard-1 if unspecified.
+ // See https://cloud.google.com/compute/docs/machine-types for more details on available machine types.
+ nodeMachineType: config.get("nodeMachineType") || "n1-standard-1",
+
+ // minMasterVersion is the minimum master version used in the cluster. Defaults to 'latest' if unspecified.
+ minMasterVersion: config.get("minMasterVersion") || "latest",
+
+ // nodeVersion is the node version used in the cluster. Defaults to 'latest' if unspecified.
+ nodeVersion: config.get("nodeVersion") || "latest"
+};

ADD
gcp-ts-gke-hello-world/index.ts
+// Copyright 2016-2019, Pulumi Corporation. All rights reserved.
+import * as k8s from "@pulumi/kubernetes";
+import * as pulumi from "@pulumi/pulumi";
+import * as gcp from "@pulumi/gcp";
+import { clusterConfig } from "./config";
+
+const name = "helloworld";
+
+// Create a GKE cluster
+const cluster = new gcp.container.Cluster(name, {
+ initialNodeCount: clusterConfig.nodeCount,
+ minMasterVersion: clusterConfig.minMasterVersion,
+ nodeVersion: clusterConfig.nodeVersion,
+ nodeConfig: {
+ machineType: clusterConfig.nodeMachineType,
+ 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,
+});
+
+// Create a Kubernetes Namespace
+const ns = new k8s.core.v1.Namespace(name, {}, { provider: clusterProvider });
+
+// Export the Namespace name
+export const namespaceName = ns.metadata.apply(m => m.name);
+
+// Create a NGINX Deployment
+const appLabels = { appClass: name };
+const deployment = new k8s.apps.v1.Deployment(name,
+ {
+ metadata: {
+ namespace: namespaceName,
+ labels: appLabels,
+ },
+ spec: {
+ replicas: 1,
+ selector: { matchLabels: appLabels },
+ template: {
+ metadata: {
+ labels: appLabels,
+ },
+ spec: {
+ containers: [
+ {
+ name: name,
+ image: "nginx:latest",
+ ports: [{ name: "http", containerPort: 80 }]
+ }
+ ],
+ }
+ }
+ },
+ },
+ {
+ provider: clusterProvider,
+ }
+);
+
+// Export the Deployment name
+export const deploymentName = deployment.metadata.apply(m => m.name);
+
+// Create a LoadBalancer Service for the NGINX Deployment
+const service = new k8s.core.v1.Service(name,
+ {
+ metadata: {
+ labels: appLabels,
+ namespace: namespaceName,
+ },
+ spec: {
+ type: "LoadBalancer",
+ ports: [{ port: 80, targetPort: "http" }],
+ selector: appLabels,
+ },
+ },
+ {
+ provider: clusterProvider,
+ }
+);
+
+// Export the Service name and public LoadBalancer endpoint
+export const serviceName = service.metadata.apply(m => m.name);
+export const servicePublicIP = service.status.apply(s => s.loadBalancer.ingress[0].ip)

ADD
gcp-ts-gke-hello-world/package.json
+{
+ "name": "gcp-ts-gke-hello-world",
+ "dependencies": {
+ "@types/node": "latest",
+ "@pulumi/gcp": "latest",
+ "@pulumi/kubernetes": "latest",
+ "@pulumi/pulumi": "latest"
+ }
+}

ADD
gcp-ts-gke-hello-world/tsconfig.json
+{
+ "compilerOptions": {
+ "outDir": "bin",
+ "target": "es6",
+ "lib": [
+ "es6"
+ ],
+ "module": "commonjs",
+ "moduleResolution": "node",
+ "sourceMap": true,
+ "experimentalDecorators": true,
+ "pretty": true,
+ "noFallthroughCasesInSwitch": true,
+ "noImplicitAny": true,
+ "noImplicitReturns": true,
+ "forceConsistentCasingInFileNames": true,
+ "strictNullChecks": true
+ },
+ "files": [
+ "index.ts",
+ "config.ts",
+ "cluster.ts"
+ ]
+}

gcp(gke): add GKE + Kubernetes Hello World