diff --git a/Gopkg.lock b/Gopkg.lock index e1cc6ca2be..891cbd6911 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -589,10 +589,11 @@ version = "v1.2.0" [[projects]] + branch = "pulumi-master" name = "github.com/terraform-providers/terraform-provider-kubernetes" packages = ["kubernetes"] - revision = "4b540ce084e2817dc255f3a22a90a692b2a4810a" - version = "v1.0.1" + revision = "0cc198319a63e0f3558a55867a5822c55859a98a" + source = "github.com/pulumi/terraform-provider-kubernetes" [[projects]] name = "github.com/uber/jaeger-client-go" @@ -849,9 +850,31 @@ name = "k8s.io/client-go" packages = [ "discovery", + "kubernetes", "kubernetes/scheme", + "kubernetes/typed/admissionregistration/v1alpha1", + "kubernetes/typed/apps/v1beta1", + "kubernetes/typed/authentication/v1", + "kubernetes/typed/authentication/v1beta1", + "kubernetes/typed/authorization/v1", + "kubernetes/typed/authorization/v1beta1", + "kubernetes/typed/autoscaling/v1", + "kubernetes/typed/autoscaling/v2alpha1", + "kubernetes/typed/batch/v1", + "kubernetes/typed/batch/v2alpha1", + "kubernetes/typed/certificates/v1beta1", + "kubernetes/typed/core/v1", + "kubernetes/typed/extensions/v1beta1", + "kubernetes/typed/networking/v1", + "kubernetes/typed/policy/v1beta1", + "kubernetes/typed/rbac/v1alpha1", + "kubernetes/typed/rbac/v1beta1", + "kubernetes/typed/settings/v1alpha1", + "kubernetes/typed/storage/v1", + "kubernetes/typed/storage/v1beta1", "pkg/api", "pkg/api/v1", + "pkg/api/v1/ref", "pkg/apis/admissionregistration", "pkg/apis/admissionregistration/v1alpha1", "pkg/apis/apps", @@ -909,87 +932,9 @@ ] revision = "d92e8497f71b7b4e0494e5bd204b48d34bd6f254" -[[projects]] - name = "k8s.io/kubernetes" - packages = [ - "pkg/api", - "pkg/api/install", - "pkg/api/v1", - "pkg/api/v1/ref", - "pkg/apis/admissionregistration", - "pkg/apis/admissionregistration/v1alpha1", - "pkg/apis/apps", - "pkg/apis/apps/install", - "pkg/apis/apps/v1beta1", - "pkg/apis/authentication", - "pkg/apis/authentication/install", - "pkg/apis/authentication/v1", - "pkg/apis/authentication/v1beta1", - "pkg/apis/authorization", - "pkg/apis/authorization/install", - "pkg/apis/authorization/v1", - "pkg/apis/authorization/v1beta1", - "pkg/apis/autoscaling", - "pkg/apis/autoscaling/install", - "pkg/apis/autoscaling/v1", - "pkg/apis/autoscaling/v2alpha1", - "pkg/apis/batch", - "pkg/apis/batch/install", - "pkg/apis/batch/v1", - "pkg/apis/batch/v2alpha1", - "pkg/apis/certificates", - "pkg/apis/certificates/install", - "pkg/apis/certificates/v1beta1", - "pkg/apis/extensions", - "pkg/apis/extensions/install", - "pkg/apis/extensions/v1beta1", - "pkg/apis/networking", - "pkg/apis/networking/v1", - "pkg/apis/policy", - "pkg/apis/policy/install", - "pkg/apis/policy/v1beta1", - "pkg/apis/rbac", - "pkg/apis/rbac/install", - "pkg/apis/rbac/v1alpha1", - "pkg/apis/rbac/v1beta1", - "pkg/apis/settings", - "pkg/apis/settings/install", - "pkg/apis/settings/v1alpha1", - "pkg/apis/storage", - "pkg/apis/storage/install", - "pkg/apis/storage/v1", - "pkg/apis/storage/v1beta1", - "pkg/client/clientset_generated/clientset", - "pkg/client/clientset_generated/clientset/scheme", - "pkg/client/clientset_generated/clientset/typed/admissionregistration/v1alpha1", - "pkg/client/clientset_generated/clientset/typed/apps/v1beta1", - "pkg/client/clientset_generated/clientset/typed/authentication/v1", - "pkg/client/clientset_generated/clientset/typed/authentication/v1beta1", - "pkg/client/clientset_generated/clientset/typed/authorization/v1", - "pkg/client/clientset_generated/clientset/typed/authorization/v1beta1", - "pkg/client/clientset_generated/clientset/typed/autoscaling/v1", - "pkg/client/clientset_generated/clientset/typed/autoscaling/v2alpha1", - "pkg/client/clientset_generated/clientset/typed/batch/v1", - "pkg/client/clientset_generated/clientset/typed/batch/v2alpha1", - "pkg/client/clientset_generated/clientset/typed/certificates/v1beta1", - "pkg/client/clientset_generated/clientset/typed/core/v1", - "pkg/client/clientset_generated/clientset/typed/extensions/v1beta1", - "pkg/client/clientset_generated/clientset/typed/networking/v1", - "pkg/client/clientset_generated/clientset/typed/policy/v1beta1", - "pkg/client/clientset_generated/clientset/typed/rbac/v1alpha1", - "pkg/client/clientset_generated/clientset/typed/rbac/v1beta1", - "pkg/client/clientset_generated/clientset/typed/settings/v1alpha1", - "pkg/client/clientset_generated/clientset/typed/storage/v1", - "pkg/client/clientset_generated/clientset/typed/storage/v1beta1", - "pkg/util", - "pkg/util/parsers" - ] - revision = "3bda299a6414b4866f179921610d6738206a18fe" - version = "v1.7.12" - [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "03f62d424ae91c7e35e097e6ee7d1d2ef024a91d229bd3b3a9ab320d3f13cb8a" + inputs-digest = "9a2b3b3417c53f1987dadf5e5d9c7edf6354350bf10239b34be4bb50a26f0285" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index ef6511b9f6..2c75f4881b 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -35,7 +35,8 @@ [[constraint]] name = "github.com/terraform-providers/terraform-provider-kubernetes" - version = "1.0.1" + source = "github.com/pulumi/terraform-provider-kubernetes" + branch = "pulumi-master" [[constraint]] name = "github.com/ghodss/yaml" diff --git a/examples/examples_test.go b/examples/examples_test.go index 6f1756555e..2e3af7028c 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -41,6 +41,7 @@ func TestExamples(t *testing.T) { if !testing.Short() { examples = append(examples, []integration.ProgramTestOptions{ base.With(integration.ProgramTestOptions{Dir: path.Join(cwd, "nginx")}), + base.With(integration.ProgramTestOptions{Dir: path.Join(cwd, "guestbook")}), }...) } diff --git a/examples/guestbook/.gitignore b/examples/guestbook/.gitignore new file mode 100644 index 0000000000..c6958891dd --- /dev/null +++ b/examples/guestbook/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/node_modules/ diff --git a/examples/guestbook/Pulumi.yaml b/examples/guestbook/Pulumi.yaml new file mode 100644 index 0000000000..bbf566474c --- /dev/null +++ b/examples/guestbook/Pulumi.yaml @@ -0,0 +1,4 @@ +name: guestbook +runtime: nodejs +description: Kubernetes Guestbook example based on https://kubernetes.io/docs/tutorials/stateless-application/guestbook/ + diff --git a/examples/guestbook/index.ts b/examples/guestbook/index.ts new file mode 100644 index 0000000000..9e712d2a72 --- /dev/null +++ b/examples/guestbook/index.ts @@ -0,0 +1,150 @@ +// Copyright 2016-2018, Pulumi Corporation. All rights reserved. + +import * as pulumi from "pulumi"; +import * as kubernetes from "@pulumi/kubernetes"; + +// REDIS MASTER + +let redisMasterLabels = { app: "redis", tier: "backend", role: "master"}; +let redisMasterService = new kubernetes.Service("redis-master", { + metadata: [{ + name: "redis-master", + labels: [redisMasterLabels], + }], + spec: [{ + port: [{ port: 6379, targetPort: 6379 }], + selector: [redisMasterLabels], + }], +}); +let redisMasterDeployment = new kubernetes.Deployment("redis-master", { + metadata: [{ + name: "redis-master", + }], + spec: [{ + selector: [redisMasterLabels], + replicas: 1, + template: [{ + metadata: [{ + labels: [redisMasterLabels], + }], + spec: [{ + container: [{ + name: "master", + image: "k8s.gcr.io/redis:e2e", + resources: [{ + requests: [{ + cpu: "100m", + memory: "100Mi", + }] + }], + port: [{ + containerPort: 6379, + }], + }], + }], + }], + }], +}); + +// REDIS SLAVE +let redisSlaveLabels = { app: "redis", tier: "backend", role: "slave" }; +let redisSlaveService = new kubernetes.Service("redis-slave", { + metadata: [{ + name: "redis-slave", + labels: [redisSlaveLabels], + }], + spec: [{ + port: [{ port: 6379, targetPort: 6379 }], + selector: [redisSlaveLabels], + }], +}); +let redisSlaveDeployment = new kubernetes.Deployment("redis-slave", { + metadata: [{ + name: "redis-slave", + }], + spec: [{ + selector: [redisSlaveLabels], + replicas: 1, + template: [{ + metadata: [{ + labels: [redisSlaveLabels], + }], + spec: [{ + container: [{ + name: "slave", + image: "gcr.io/google_samples/gb-redisslave:v1", + resources: [{ + requests: [{ + cpu: "100m", + memory: "100Mi", + }] + }], + env: [{ + name: "GET_HOSTS_FROM", + value: "dns", + // If your cluster config does not include a dns service, then to instead access an environment + // variable to find the master service's host, comment out the 'value: dns' line above, and + // uncomment the line below: + // value: "env" + }], + port: [{ + containerPort: 6379, + }], + }], + }], + }], + }], +}); + +// FRONTEND +let frontendLabels = { app: "guestbook", tier: "frontend" }; +let frontendService = new kubernetes.Service("frontend", { + metadata: [{ + name: "frontend", + labels: [frontendLabels], + }], + spec: [{ + // If your cluster supports it, uncomment the following to automatically create + // an external load-balanced IP for the frontend service. + // type: LoadBalancer + port: [{ port: 80 }], + selector: [frontendLabels], + }], +}); +let frontendDeployment = new kubernetes.Deployment("frontend", { + metadata: [{ + name: "frontend", + }], + spec: [{ + selector: [frontendLabels], + replicas: 3, + template: [{ + metadata: [{ + labels: [frontendLabels], + }], + spec: [{ + container: [{ + name: "php-redis", + image: "gcr.io/google-samples/gb-frontend:v4", + resources: [{ + requests: [{ + cpu: "100m", + memory: "100Mi", + }] + }], + env: [{ + name: "GET_HOSTS_FROM", + value: "dns", + // If your cluster config does not include a dns service, then to instead access an environment + // variable to find the master service's host, comment out the 'value: dns' line above, and + // uncomment the line below: + // value: "env" + }], + port: [{ + containerPort: 80, + }], + }], + }], + }], + }], +}); diff --git a/examples/guestbook/package.json b/examples/guestbook/package.json new file mode 100644 index 0000000000..3725489364 --- /dev/null +++ b/examples/guestbook/package.json @@ -0,0 +1,18 @@ +{ + "name": "guestbook", + "version": "0.1", + "main": "bin/index.js", + "typings": "bin/index.d.ts", + "scripts": { + "build": "tsc" + }, + "devDependencies": { + "@types/node": "^9.3.0", + "typescript": "^2.5.3" + }, + "peerDependencies": { + "@pulumi/kubernetes": "*", + "pulumi": "*" + }, + "license": "MIT" +} diff --git a/examples/guestbook/tsconfig.json b/examples/guestbook/tsconfig.json new file mode 100644 index 0000000000..3086b63abd --- /dev/null +++ b/examples/guestbook/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "outDir": "bin", + "target": "es6", + "module": "commonjs", + "moduleResolution": "node", + "declaration": true, + "sourceMap": true, + "stripInternal": true, + "experimentalDecorators": true, + "pretty": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitReturns": true, + "forceConsistentCasingInFileNames": true, + "strictNullChecks": true + }, + "files": [ + "index.ts" + ] +} diff --git a/examples/guestbook/yarn.lock b/examples/guestbook/yarn.lock new file mode 100644 index 0000000000..8b1004fa8f --- /dev/null +++ b/examples/guestbook/yarn.lock @@ -0,0 +1,11 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@^9.3.0": + version "9.4.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-9.4.0.tgz#b85a0bcf1e1cc84eb4901b7e96966aedc6f078d1" + +typescript@^2.5.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.1.tgz#bb3682c2c791ac90e7c6210b26478a8da085c359" diff --git a/examples/nginx/index.ts b/examples/nginx/index.ts index 4912e40809..01fb22ccaf 100644 --- a/examples/nginx/index.ts +++ b/examples/nginx/index.ts @@ -1,6 +1,6 @@ -import * as kubernetes from "@pulumi/kubernetes"; +// Copyright 2016-2018, Pulumi Corporation. All rights reserved. -kubernetes.config.host = process.env.host; +import * as kubernetes from "@pulumi/kubernetes"; // Create an nginx pod let nginxcontainer = new kubernetes.Pod("nginx", { diff --git a/resources.go b/resources.go index 1989f32e3d..7eb667d0c1 100644 --- a/resources.go +++ b/resources.go @@ -3,92 +3,83 @@ package kubernetes import ( - "unicode" + "unicode" - "github.com/hashicorp/terraform/helper/schema" - "github.com/pulumi/pulumi-terraform/pkg/tfbridge" - "github.com/pulumi/pulumi/pkg/tokens" - kubernetes "github.com/terraform-providers/terraform-provider-kubernetes/kubernetes" + "github.com/hashicorp/terraform/helper/schema" + "github.com/pulumi/pulumi-terraform/pkg/tfbridge" + "github.com/pulumi/pulumi/pkg/tokens" + kubernetes "github.com/terraform-providers/terraform-provider-kubernetes/kubernetes" ) // all of the Kubernetes token components used below. const ( - // packages: - kubernetesPkg = "kubernetes" - kubernetesCore = "" //Resources + // packages: + kubernetesPkg = "kubernetes" + kubernetesCore = "" // All resources are placed in the root `kubernetes` namespace ) // kubernetesMember manufactures a type token for the Kubernetes package and the given module and type. func kubernetesMember(mod string, mem string) tokens.ModuleMember { - return tokens.ModuleMember(kubernetesPkg + ":" + mod + ":" + mem) + return tokens.ModuleMember(kubernetesPkg + ":" + mod + ":" + mem) } // kubernetesType manufactures a type token for the Kubernetes package and the given module and type. func kubernetesType(mod string, typ string) tokens.Type { - return tokens.Type(kubernetesMember(mod, typ)) + return tokens.Type(kubernetesMember(mod, typ)) } // kubernetesDataSource manufactures a standard resource token given a module and resource name. It automatically uses the Kubernetes // package and names the file by simply lower casing the data source's first character. func kubernetesDataSource(mod string, res string) tokens.ModuleMember { - fn := string(unicode.ToLower(rune(res[0]))) + res[1:] - return kubernetesMember(mod+"/"+fn, res) + fn := string(unicode.ToLower(rune(res[0]))) + res[1:] + return kubernetesMember(mod+"/"+fn, res) } // kubernetesResource manufactures a standard resource token given a module and resource name. It automatically uses the Kubernetes // package and names the file by simply lower casing the resource's first character. func kubernetesResource(mod string, res string) tokens.Type { - fn := string(unicode.ToLower(rune(res[0]))) + res[1:] - return kubernetesType(mod+"/"+fn, res) + fn := string(unicode.ToLower(rune(res[0]))) + res[1:] + return kubernetesType(mod+"/"+fn, res) } // Provider returns additional overlaid schema and metadata associated with the Kubernetes package. func Provider() tfbridge.ProviderInfo { - p := kubernetes.Provider().(*schema.Provider) - prov := tfbridge.ProviderInfo{ - P: p, - Name: "kubernetes", - Resources: map[string]*tfbridge.ResourceInfo{ - "kubernetes_config_map": {Tok: kubernetesResource(kubernetesCore, "ConfigMap")}, - "kubernetes_horizontal_pod_autoscaler": {Tok: kubernetesResource(kubernetesCore, "HorizontalPodAutoscaler")}, - "kubernetes_limit_range": {Tok: kubernetesResource(kubernetesCore, "LimitRange")}, - "kubernetes_namespace": {Tok: kubernetesResource(kubernetesCore, "Namespace")}, - "kubernetes_persistent_volume": {Tok: kubernetesResource(kubernetesCore, "PersistentVolume")}, - "kubernetes_persistent_volume_claim": {Tok: kubernetesResource(kubernetesCore, "PersistentVolumeClaim")}, - "kubernetes_pod": {Tok: kubernetesResource(kubernetesCore, "Pod")}, - "kubernetes_replication_controller": {Tok: kubernetesResource(kubernetesCore, "ReplicationController")}, - "kubernetes_resource_quota": {Tok: kubernetesResource(kubernetesCore, "ResourceQuota")}, - "kubernetes_secret": {Tok: kubernetesResource(kubernetesCore, "Secret")}, - "kubernetes_service": {Tok: kubernetesResource(kubernetesCore, "Service")}, - "kubernetes_service_account": {Tok: kubernetesResource(kubernetesCore, "ServiceAccount")}, - "kubernetes_storage_class": {Tok: kubernetesResource(kubernetesCore, "StorageClass")}, - }, - DataSources: map[string]*tfbridge.DataSourceInfo{ - "kubernetes_service": {Tok: kubernetesDataSource(kubernetesCore, "getService")}, - "kubernetes_storage_class": {Tok: kubernetesDataSource(kubernetesCore, "getStorageClass")}, - }, - Overlay: &tfbridge.OverlayInfo{ - Files: []string{}, - Modules: map[string]*tfbridge.OverlayInfo{}, - Dependencies: map[string]string{}, - }, - } + p := kubernetes.Provider().(*schema.Provider) + prov := tfbridge.ProviderInfo{ + P: p, + Name: "kubernetes", + Resources: map[string]*tfbridge.ResourceInfo{ + "kubernetes_config_map": {Tok: kubernetesResource(kubernetesCore, "ConfigMap")}, + "kubernetes_daemonset": {Tok: kubernetesResource(kubernetesCore, "DaemonSet")}, + "kubernetes_deployment": {Tok: kubernetesResource(kubernetesCore, "Deployment")}, + "kubernetes_horizontal_pod_autoscaler": {Tok: kubernetesResource(kubernetesCore, "HorizontalPodAutoscaler")}, + "kubernetes_ingress": {Tok: kubernetesResource(kubernetesCore, "Ingres")}, + "kubernetes_job": {Tok: kubernetesResource(kubernetesCore, "Job")}, + "kubernetes_limit_range": {Tok: kubernetesResource(kubernetesCore, "LimitRange")}, + "kubernetes_namespace": {Tok: kubernetesResource(kubernetesCore, "Namespace")}, + "kubernetes_persistent_volume": {Tok: kubernetesResource(kubernetesCore, "PersistentVolume")}, + "kubernetes_persistent_volume_claim": {Tok: kubernetesResource(kubernetesCore, "PersistentVolumeClaim")}, + "kubernetes_pod": {Tok: kubernetesResource(kubernetesCore, "Pod")}, + "kubernetes_replication_controller": {Tok: kubernetesResource(kubernetesCore, "ReplicationController")}, + "kubernetes_resource_quota": {Tok: kubernetesResource(kubernetesCore, "ResourceQuota")}, + "kubernetes_secret": {Tok: kubernetesResource(kubernetesCore, "Secret")}, + "kubernetes_service": {Tok: kubernetesResource(kubernetesCore, "Service")}, + "kubernetes_service_account": {Tok: kubernetesResource(kubernetesCore, "ServiceAccount")}, + "kubernetes_stateful_set": {Tok: kubernetesResource(kubernetesCore, "StatefulSet")}, + "kubernetes_storage_class": {Tok: kubernetesResource(kubernetesCore, "StorageClass")}, + }, + DataSources: map[string]*tfbridge.DataSourceInfo{ + "kubernetes_service": {Tok: kubernetesDataSource(kubernetesCore, "getService")}, + "kubernetes_storage_class": {Tok: kubernetesDataSource(kubernetesCore, "getStorageClass")}, + }, + Overlay: &tfbridge.OverlayInfo{ + Files: []string{}, + Modules: map[string]*tfbridge.OverlayInfo{}, + Dependencies: map[string]string{}, + }, + } - // For all resources with name properties, we will add an auto-name property. Make sure to skip those that - // already have a name mapping entry, since those may have custom overrides set above (e.g., for length). - const kubernetesName = "name" - for resname, res := range prov.Resources { - if schema := p.ResourcesMap[resname]; schema != nil { - if _, has := schema.Schema[kubernetesName]; has { - if _, hasfield := res.Fields[kubernetesName]; !hasfield { - if res.Fields == nil { - res.Fields = make(map[string]*tfbridge.SchemaInfo) - } - res.Fields[kubernetesName] = tfbridge.AutoName(kubernetesName, 255) - } - } - } - } + // TODO[pulumi/pulumi-kubernetes#10: Auto-populate `res.metadata.name` - return prov -} \ No newline at end of file + return prov +}