diff --git a/.gitignore b/.gitignore index a3cd69d3ea..adc559fe94 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ website/vendor # Test exclusions !command/test-fixtures/**/*.tfstate !command/test-fixtures/**/.terraform/ +**/terraform-provider-kubernetes +**/terraform-provider-kubernetes-yaml diff --git a/_examples/yaml/main.tf b/_examples/yaml/main.tf new file mode 100644 index 0000000000..47192f8a82 --- /dev/null +++ b/_examples/yaml/main.tf @@ -0,0 +1,39 @@ +provider "kubernetes" {} + +resource "kubernetes_yaml" "test" { + yaml_body = < dply.Status.UpdatedReplicas { - return resource.RetryableError(fmt.Errorf("Waiting for rollout to finish: %d old replicas are pending termination...", dply.Status.Replicas-dply.Status.UpdatedReplicas)) - } - - if dply.Status.AvailableReplicas < dply.Status.UpdatedReplicas { - return resource.RetryableError(fmt.Errorf("Waiting for rollout to finish: %d of %d updated replicas are available...", dply.Status.AvailableReplicas, dply.Status.UpdatedReplicas)) - } - } - return nil - } -} diff --git a/kubernetes/resource_kubernetes_deployment_test.go b/kubernetes/resource_kubernetes_deployment_test.go deleted file mode 100644 index bebf06a91f..0000000000 --- a/kubernetes/resource_kubernetes_deployment_test.go +++ /dev/null @@ -1,1016 +0,0 @@ -package kubernetes - -import ( - "fmt" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/apps/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesDeployment_basic(t *testing.T) { - var conf api.Deployment - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_deployment.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.image", "nginx:1.7.8"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.name", "tf-acc-test"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_initContainer(t *testing.T) { - var conf api.Deployment - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_deployment.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfig_initContainer(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.image", "busybox"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.name", "install"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.command.0", "wget"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.command.1", "-O"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.command.2", "/work-dir/index.html"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.command.3", "http://kubernetes.io"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.volume_mount.0.name", "workdir"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.init_container.0.volume_mount.0.mount_path", "/work-dir"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_importBasic(t *testing.T) { - resourceName := "kubernetes_deployment.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfig_basic(name), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesDeployment_generatedName(t *testing.T) { - var conf api.Deployment - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_deployment.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.labels.%", "3"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_deployment.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_deployment.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_deployment.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfig_generatedName(prefix), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_security_context(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithSecurityContext(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.security_context.0.run_as_non_root", "true"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.security_context.0.run_as_user", "101"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.security_context.0.supplemental_groups.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.security_context.0.supplemental_groups.988695518", "101"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_container_liveness_probe_using_exec(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/busybox" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithLivenessProbeUsingExec(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.args.#", "3"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.exec.0.command.0", "cat"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.exec.0.command.1", "/tmp/healthy"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.failure_threshold", "3"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.initial_delay_seconds", "5"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_container_liveness_probe_using_http_get(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithLivenessProbeUsingHTTPGet(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.0.path", "/healthz"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.0.port", "8080"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.0.http_header.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.0.http_header.0.name", "X-Custom-Header"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.http_get.0.http_header.0.value", "Awesome"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.initial_delay_seconds", "3"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_container_liveness_probe_using_tcp(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithLivenessProbeUsingTCP(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.tcp_socket.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.liveness_probe.0.tcp_socket.0.port", "8080"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_container_lifecycle(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithLifeCycle(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.post_start.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.post_start.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.0", "ls"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.1", "-al"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.pre_stop.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.pre_stop.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.0", "date"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_container_security_context(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithContainerSecurityContext(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.security_context.#", "1"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_volume_mount(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithVolumeMounts(secretName, rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/tmp/my_path"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "db"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.read_only", "false"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.sub_path", ""), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_resource_requirements(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithResourceRequirements(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.requests.0.memory", "50Mi"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.requests.0.cpu", "250m"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.limits.0.memory", "512Mi"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.resources.0.limits.0.cpu", "500m"), - ), - }, - }, - }) -} - -func TestAccKubernetesDeployment_with_empty_dir_volume(t *testing.T) { - var conf api.Deployment - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesDeploymentDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesDeploymentConfigWithEmptyDirVolumes(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesDeploymentExists("kubernetes_deployment.test", &conf), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.mount_path", "/cache"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.container.0.volume_mount.0.name", "cache-volume"), - resource.TestCheckResourceAttr("kubernetes_deployment.test", "spec.0.template.0.spec.0.volume.0.empty_dir.0.medium", "Memory"), - ), - }, - }, - }) -} - -func testAccCheckKubernetesDeploymentDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_deployment" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.AppsV1().Deployments(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Deployment still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesDeploymentExists(n string, obj *api.Deployment) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.AppsV1().Deployments(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesDeploymentConfig_basic(name string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - replicas = 1000 # This is intentionally high to exercise the waiter - selector { - match_labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - template { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - spec { - container { - image = "nginx:1.7.8" - name = "tf-acc-test" - } - } - } - } - } -`, name) -} - -func testAccKubernetesDeploymentConfig_initContainer(name string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - replicas = 1000 # This is intentionally high to exercise the waiter - selector { - match_labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - template { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - spec { - container { - name = "nginx" - image = "nginx" - - port { - container_port = 80 - } - - volume_mount { - name = "workdir" - mount_path = "/usr/share/nginx/html" - } - } - init_container { - name = "install" - image = "busybox" - command = ["wget", "-O", "/work-dir/index.html", "http://kubernetes.io"] - - volume_mount { - name = "workdir" - mount_path = "/work-dir" - } - } - dns_policy = "Default" - volume { - name = "workdir" - empty_dir = {} - } - } - } - } - }`, name) -} - -func testAccKubernetesDeploymentConfig_modified(name string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - spec { - selector { - match_labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - template { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - spec { - container { - image = "nginx:1.7.9" - name = "tf-acc-test" - } - } - } - } - }`, name) -} - -func testAccKubernetesDeploymentConfig_generatedName(prefix string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - generate_name = "%s" - } - spec { - selector { - match_labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - template { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - } - spec { - container { - image = "nginx:1.7.9" - name = "tf-acc-test" - } - } - } - } - }`, prefix) -} - -func testAccKubernetesDeploymentConfigWithSecurityContext(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - security_context { - run_as_non_root = true - run_as_user = 101 - supplemental_groups = [101] - } - container { - image = "%s" - name = "containername" - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithLivenessProbeUsingExec(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - args = ["/bin/sh", "-c", "touch /tmp/healthy; sleep 300; rm -rf /tmp/healthy; sleep 600"] - liveness_probe { - exec { - command = ["cat", "/tmp/healthy"] - } - initial_delay_seconds = 5 - period_seconds = 5 - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithLivenessProbeUsingHTTPGet(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - liveness_probe { - http_get { - path = "/healthz" - port = 8080 - http_header { - name = "X-Custom-Header" - value = "Awesome" - } - } - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithLivenessProbeUsingTCP(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - liveness_probe { - tcp_socket { - port = 8080 - } - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithLifeCycle(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - lifecycle { - post_start { - exec { - command = ["ls", "-al"] - } - } - pre_stop { - exec { - command = ["date"] - } - } - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithContainerSecurityContext(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - security_context { - privileged = true - run_as_user = 1 - se_linux_options { - level = "s0:c123,c456" - } - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithVolumeMounts(secretName, rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - data { - one = "first" - } - } - - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/tmp/my_path" - name = "db" - } - } - volume { - name = "db" - secret = { - secret_name = "${kubernetes_secret.test.metadata.0.name}" - } - } - } - } - } - }`, secretName, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithResourceRequirements(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - resources { - limits { - cpu = "0.5" - memory = "512Mi" - } - requests { - cpu = "250m" - memory = "50Mi" - } - } - } - } - } - } - }`, rcName, imageName) -} - -func testAccKubernetesDeploymentConfigWithEmptyDirVolumes(rcName, imageName string) string { - return fmt.Sprintf(` - resource "kubernetes_deployment" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - match_labels { - Test = "TfAcceptanceTest" - } - } - template { - metadata { - labels { - Test = "TfAcceptanceTest" - } - } - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/cache" - name = "cache-volume" - } - } - volume { - name = "cache-volume" - empty_dir = { - medium = "Memory" - } - } - } - } - } - }`, rcName, imageName) -} diff --git a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler.go b/kubernetes/resource_kubernetes_horizontal_pod_autoscaler.go deleted file mode 100644 index 75075c63fd..0000000000 --- a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler.go +++ /dev/null @@ -1,197 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/autoscaling/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesHorizontalPodAutoscaler() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesHorizontalPodAutoscalerCreate, - Read: resourceKubernetesHorizontalPodAutoscalerRead, - Exists: resourceKubernetesHorizontalPodAutoscalerExists, - Update: resourceKubernetesHorizontalPodAutoscalerUpdate, - Delete: resourceKubernetesHorizontalPodAutoscalerDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("horizontal pod autoscaler", true), - "spec": { - Type: schema.TypeList, - Description: "Behaviour of the autoscaler. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "max_replicas": { - Type: schema.TypeInt, - Description: "Upper limit for the number of pods that can be set by the autoscaler.", - Required: true, - }, - "min_replicas": { - Type: schema.TypeInt, - Description: "Lower limit for the number of pods that can be set by the autoscaler, defaults to `1`.", - Optional: true, - Default: 1, - }, - "scale_target_ref": { - Type: schema.TypeList, - Description: "Reference to scaled resource. e.g. Replication Controller", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "api_version": { - Type: schema.TypeString, - Description: "API version of the referent", - Optional: true, - }, - "kind": { - Type: schema.TypeString, - Description: "Kind of the referent. e.g. `ReplicationController`. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds", - Required: true, - }, - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Required: true, - }, - }, - }, - }, - "target_cpu_utilization_percentage": { - Type: schema.TypeInt, - Description: "Target average CPU utilization (represented as a percentage of requested CPU) over all the pods. If not specified the default autoscaling policy will be used.", - Optional: true, - Computed: true, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesHorizontalPodAutoscalerCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - svc := api.HorizontalPodAutoscaler{ - ObjectMeta: metadata, - Spec: expandHorizontalPodAutoscalerSpec(d.Get("spec").([]interface{})), - } - log.Printf("[INFO] Creating new horizontal pod autoscaler: %#v", svc) - out, err := conn.AutoscalingV1().HorizontalPodAutoscalers(metadata.Namespace).Create(&svc) - if err != nil { - return err - } - - log.Printf("[INFO] Submitted new horizontal pod autoscaler: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesHorizontalPodAutoscalerRead(d, meta) -} - -func resourceKubernetesHorizontalPodAutoscalerRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - log.Printf("[INFO] Reading horizontal pod autoscaler %s", name) - svc, err := conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received horizontal pod autoscaler: %#v", svc) - err = d.Set("metadata", flattenMetadata(svc.ObjectMeta)) - if err != nil { - return err - } - - flattened := flattenHorizontalPodAutoscalerSpec(svc.Spec) - log.Printf("[DEBUG] Flattened horizontal pod autoscaler spec: %#v", flattened) - err = d.Set("spec", flattened) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesHorizontalPodAutoscalerUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("spec") { - diffOps := patchHorizontalPodAutoscalerSpec("spec.0.", "/spec", d) - ops = append(ops, diffOps...) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating horizontal pod autoscaler %q: %v", name, string(data)) - out, err := conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update horizontal pod autoscaler: %s", err) - } - log.Printf("[INFO] Submitted updated horizontal pod autoscaler: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesHorizontalPodAutoscalerRead(d, meta) -} - -func resourceKubernetesHorizontalPodAutoscalerDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - log.Printf("[INFO] Deleting horizontal pod autoscaler: %#v", name) - err = conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Horizontal Pod Autoscaler %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesHorizontalPodAutoscalerExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking horizontal pod autoscaler %s", name) - _, err = conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_test.go b/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_test.go deleted file mode 100644 index 13d71180a0..0000000000 --- a/kubernetes/resource_kubernetes_horizontal_pod_autoscaler_test.go +++ /dev/null @@ -1,288 +0,0 @@ -package kubernetes - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/autoscaling/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesHorizontalPodAutoscaler_basic(t *testing.T) { - var conf api.HorizontalPodAutoscaler - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_horizontal_pod_autoscaler.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesHorizontalPodAutoscalerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesHorizontalPodAutoscalerConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesHorizontalPodAutoscalerExists("kubernetes_horizontal_pod_autoscaler.test", &conf), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.%", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.TestAnnotationOne", "one"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one"}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelThree", "three"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelFour", "four"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three", "TestLabelFour": "four"}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.max_replicas", "10"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.min_replicas", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.kind", "ReplicationController"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.name", "TerraformAccTest"), - ), - }, - { - Config: testAccKubernetesHorizontalPodAutoscalerConfig_metaModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesHorizontalPodAutoscalerExists("kubernetes_horizontal_pod_autoscaler.test", &conf), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.max_replicas", "10"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.min_replicas", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.kind", "ReplicationController"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.name", "TerraformAccTest"), - ), - }, - { - Config: testAccKubernetesHorizontalPodAutoscalerConfig_specModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesHorizontalPodAutoscalerExists("kubernetes_horizontal_pod_autoscaler.test", &conf), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.max_replicas", "8"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.min_replicas", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.kind", "ReplicationController"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.name", "TerraformAccTestModified"), - ), - }, - }, - }) -} - -func TestAccKubernetesHorizontalPodAutoscaler_generatedName(t *testing.T) { - var conf api.HorizontalPodAutoscaler - prefix := "tf-acc-test-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_horizontal_pod_autoscaler.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesHorizontalPodAutoscalerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesHorizontalPodAutoscalerConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesHorizontalPodAutoscalerExists("kubernetes_horizontal_pod_autoscaler.test", &conf), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.generate_name", prefix), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_horizontal_pod_autoscaler.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.max_replicas", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.min_replicas", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.kind", "ReplicationController"), - resource.TestCheckResourceAttr("kubernetes_horizontal_pod_autoscaler.test", "spec.0.scale_target_ref.0.name", "TerraformAccTestGeneratedName"), - ), - }, - }, - }) -} - -func TestAccKubernetesHorizontalPodAutoscaler_importBasic(t *testing.T) { - resourceName := "kubernetes_horizontal_pod_autoscaler.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesHorizontalPodAutoscalerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesHorizontalPodAutoscalerConfig_basic(name), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func testAccCheckKubernetesHorizontalPodAutoscalerDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_horizontal_pod_autoscaler" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Namespace == namespace && resp.Name == name { - return fmt.Errorf("Horizontal Pod Autoscaler still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesHorizontalPodAutoscalerExists(n string, obj *api.HorizontalPodAutoscaler) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesHorizontalPodAutoscalerConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_horizontal_pod_autoscaler" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - TestLabelFour = "four" - } - name = "%s" - } - spec { - max_replicas = 10 - scale_target_ref { - kind = "ReplicationController" - name = "TerraformAccTest" - } - } -} -`, name) -} - -func testAccKubernetesHorizontalPodAutoscalerConfig_metaModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_horizontal_pod_autoscaler" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - max_replicas = 10 - scale_target_ref { - kind = "ReplicationController" - name = "TerraformAccTest" - } - } -} -`, name) -} - -func testAccKubernetesHorizontalPodAutoscalerConfig_specModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_horizontal_pod_autoscaler" "test" { - metadata { - name = "%s" - } - spec { - max_replicas = 8 - scale_target_ref { - kind = "ReplicationController" - name = "TerraformAccTestModified" - } - } -} -`, name) -} - -func testAccKubernetesHorizontalPodAutoscalerConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_horizontal_pod_autoscaler" "test" { - metadata { - generate_name = "%s" - } - spec { - max_replicas = 1 - scale_target_ref { - kind = "ReplicationController" - name = "TerraformAccTestGeneratedName" - } - } -} -`, prefix) -} diff --git a/kubernetes/resource_kubernetes_limit_range.go b/kubernetes/resource_kubernetes_limit_range.go deleted file mode 100644 index 345200d7ac..0000000000 --- a/kubernetes/resource_kubernetes_limit_range.go +++ /dev/null @@ -1,203 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesLimitRange() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesLimitRangeCreate, - Read: resourceKubernetesLimitRangeRead, - Exists: resourceKubernetesLimitRangeExists, - Update: resourceKubernetesLimitRangeUpdate, - Delete: resourceKubernetesLimitRangeDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("limit range", true), - "spec": { - Type: schema.TypeList, - Description: "Spec defines the limits enforced. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "limit": { - Type: schema.TypeList, - Description: "Limits is the list of objects that are enforced.", - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "default": { - Type: schema.TypeMap, - Description: "Default resource requirement limit value by resource name if resource limit is omitted.", - Optional: true, - }, - "default_request": { - Type: schema.TypeMap, - Description: "The default resource requirement request value by resource name if resource request is omitted.", - Optional: true, - Computed: true, - }, - "max": { - Type: schema.TypeMap, - Description: "Max usage constraints on this kind by resource name.", - Optional: true, - }, - "max_limit_request_ratio": { - Type: schema.TypeMap, - Description: "The named resource must have a request and limit that are both non-zero where limit divided by request is less than or equal to the enumerated value; this represents the max burst for the named resource.", - Optional: true, - }, - "min": { - Type: schema.TypeMap, - Description: "Min usage constraints on this kind by resource name.", - Optional: true, - }, - "type": { - Type: schema.TypeString, - Description: "Type of resource that this limit applies to.", - Optional: true, - }, - }, - }, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesLimitRangeCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandLimitRangeSpec(d.Get("spec").([]interface{}), d.IsNewResource()) - if err != nil { - return err - } - limitRange := api.LimitRange{ - ObjectMeta: metadata, - Spec: spec, - } - log.Printf("[INFO] Creating new limit range: %#v", limitRange) - out, err := conn.CoreV1().LimitRanges(metadata.Namespace).Create(&limitRange) - if err != nil { - return fmt.Errorf("Failed to create limit range: %s", err) - } - log.Printf("[INFO] Submitted new limit range: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesLimitRangeRead(d, meta) -} - -func resourceKubernetesLimitRangeRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - log.Printf("[INFO] Reading limit range %s", name) - limitRange, err := conn.CoreV1().LimitRanges(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received limit range: %#v", limitRange) - - err = d.Set("metadata", flattenMetadata(limitRange.ObjectMeta)) - if err != nil { - return err - } - err = d.Set("spec", flattenLimitRangeSpec(limitRange.Spec)) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesLimitRangeUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("spec") { - spec, err := expandLimitRangeSpec(d.Get("spec").([]interface{}), d.IsNewResource()) - if err != nil { - return err - } - ops = append(ops, &ReplaceOperation{ - Path: "/spec", - Value: spec, - }) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating limit range %q: %v", name, string(data)) - out, err := conn.CoreV1().LimitRanges(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update limit range: %s", err) - } - log.Printf("[INFO] Submitted updated limit range: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesLimitRangeRead(d, meta) -} - -func resourceKubernetesLimitRangeDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting limit range: %#v", name) - err = conn.CoreV1().LimitRanges(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Limit range %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesLimitRangeExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking limit range %s", name) - _, err = conn.CoreV1().LimitRanges(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_limit_range_test.go b/kubernetes/resource_kubernetes_limit_range_test.go deleted file mode 100644 index 528965df2a..0000000000 --- a/kubernetes/resource_kubernetes_limit_range_test.go +++ /dev/null @@ -1,527 +0,0 @@ -package kubernetes - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesLimitRange_basic(t *testing.T) { - var conf api.LimitRange - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_limit_range.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.TestAnnotationOne", "one"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one"}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelThree", "three"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelFour", "four"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three", "TestLabelFour": "four"}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.memory", "512M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.cpu", "100m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.memory", "256M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Container"), - ), - }, - { - Config: testAccKubernetesLimitRangeConfig_metaModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.memory", "512M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.cpu", "100m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.memory", "256M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Container"), - ), - }, - { - Config: testAccKubernetesLimitRangeConfig_specModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.memory", "1024M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.cpu", "100m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default_request.memory", "256M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.max.%", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.max.cpu", "500m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.cpu", "10m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.memory", "10M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Container"), - ), - }, - }, - }) -} - -func TestAccKubernetesLimitRange_empty(t *testing.T) { - var conf api.LimitRange - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_limit_range.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_empty(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.#", "0"), - ), - }, - }, - }) -} - -func TestAccKubernetesLimitRange_generatedName(t *testing.T) { - var conf api.LimitRange - prefix := "tf-acc-test-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_limit_range.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.generate_name", prefix), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Pod"), - ), - }, - }, - }) -} - -func TestAccKubernetesLimitRange_typeChange(t *testing.T) { - var conf api.LimitRange - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_limit_range.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_typeChange(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.default.memory", "1024M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Container"), - ), - }, - { - Config: testAccKubernetesLimitRangeConfig_typeChangeModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.min.memory", "1024M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Pod"), - ), - }, - }, - }) -} - -func TestAccKubernetesLimitRange_multipleLimits(t *testing.T) { - var conf api.LimitRange - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_limit_range.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_multipleLimits(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesLimitRangeExists("kubernetes_limit_range.test", &conf), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_limit_range.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.#", "3"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.max.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.max.cpu", "200m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.max.memory", "1024M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.0.type", "Pod"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.1.min.%", "1"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.1.min.storage", "24M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.1.type", "PersistentVolumeClaim"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.2.default.%", "2"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.2.default.cpu", "50m"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.2.default.memory", "24M"), - resource.TestCheckResourceAttr("kubernetes_limit_range.test", "spec.0.limit.2.type", "Container"), - ), - }, - }, - }) -} - -func TestAccKubernetesLimitRange_importBasic(t *testing.T) { - resourceName := "kubernetes_limit_range.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesLimitRangeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesLimitRangeConfig_basic(name), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func testAccCheckKubernetesLimitRangeDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_limit_range" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().LimitRanges(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Namespace == namespace && resp.Name == name { - return fmt.Errorf("Limit Range still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesLimitRangeExists(n string, obj *api.LimitRange) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().LimitRanges(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesLimitRangeConfig_empty(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - name = "%s" - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - TestLabelFour = "four" - } - name = "%s" - } - spec { - limit { - type = "Container" - - default { - cpu = "200m" - memory = "512M" - } - - default_request { - cpu = "100m" - memory = "256M" - } - } - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_metaModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - limit { - type = "Container" - - default { - cpu = "200m" - memory = "512M" - } - - default_request { - cpu = "100m" - memory = "256M" - } - } - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_specModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - name = "%s" - } - spec { - limit { - type = "Container" - - default { - cpu = "200m" - memory = "1024M" - } - - max { - cpu = "500m" - } - - min { - cpu = "10m" - memory = "10M" - } - } - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - generate_name = "%s" - } - spec { - limit { - type = "Pod" - } - } -} -`, prefix) -} - -func testAccKubernetesLimitRangeConfig_typeChange(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - name = "%s" - } - spec { - limit { - type = "Container" - default { - cpu = "200m" - memory = "1024M" - } - } - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_typeChangeModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - name = "%s" - } - spec { - limit { - type = "Pod" - min { - cpu = "200m" - memory = "1024M" - } - } - } -} -`, name) -} - -func testAccKubernetesLimitRangeConfig_multipleLimits(name string) string { - return fmt.Sprintf(` -resource "kubernetes_limit_range" "test" { - metadata { - name = "%s" - } - spec { - limit { - type = "Pod" - max { - cpu = "200m" - memory = "1024M" - } - } - limit { - type = "PersistentVolumeClaim" - min { - storage = "24M" - } - } - limit { - type = "Container" - default { - cpu = "50m" - memory = "24M" - } - } - } -} -`, name) -} diff --git a/kubernetes/resource_kubernetes_namespace.go b/kubernetes/resource_kubernetes_namespace.go deleted file mode 100644 index 91fb86615f..0000000000 --- a/kubernetes/resource_kubernetes_namespace.go +++ /dev/null @@ -1,144 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesNamespace() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesNamespaceCreate, - Read: resourceKubernetesNamespaceRead, - Exists: resourceKubernetesNamespaceExists, - Update: resourceKubernetesNamespaceUpdate, - Delete: resourceKubernetesNamespaceDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": metadataSchema("namespace", true), - }, - } -} - -func resourceKubernetesNamespaceCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - namespace := api.Namespace{ - ObjectMeta: metadata, - } - log.Printf("[INFO] Creating new namespace: %#v", namespace) - out, err := conn.CoreV1().Namespaces().Create(&namespace) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new namespace: %#v", out) - d.SetId(out.Name) - - return resourceKubernetesNamespaceRead(d, meta) -} - -func resourceKubernetesNamespaceRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Reading namespace %s", name) - namespace, err := conn.CoreV1().Namespaces().Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received namespace: %#v", namespace) - err = d.Set("metadata", flattenMetadata(namespace.ObjectMeta)) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesNamespaceUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - ops := patchMetadata("metadata.0.", "/metadata/", d) - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - - log.Printf("[INFO] Updating namespace: %s", ops) - out, err := conn.CoreV1().Namespaces().Patch(d.Id(), pkgApi.JSONPatchType, data) - if err != nil { - return err - } - log.Printf("[INFO] Submitted updated namespace: %#v", out) - d.SetId(out.Name) - - return resourceKubernetesNamespaceRead(d, meta) -} - -func resourceKubernetesNamespaceDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Deleting namespace: %#v", name) - err := conn.CoreV1().Namespaces().Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - stateConf := &resource.StateChangeConf{ - Target: []string{}, - Pending: []string{"Terminating"}, - Timeout: 5 * time.Minute, - Refresh: func() (interface{}, string, error) { - out, err := conn.CoreV1().Namespaces().Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return nil, "", nil - } - log.Printf("[ERROR] Received error: %#v", err) - return out, "Error", err - } - - statusPhase := fmt.Sprintf("%v", out.Status.Phase) - log.Printf("[DEBUG] Namespace %s status received: %#v", out.Name, statusPhase) - return out, statusPhase, nil - }, - } - _, err = stateConf.WaitForState() - if err != nil { - return err - } - log.Printf("[INFO] Namespace %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesNamespaceExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Checking namespace %s", name) - _, err := conn.CoreV1().Namespaces().Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - log.Printf("[INFO] Namespace %s exists", name) - return true, err -} diff --git a/kubernetes/resource_kubernetes_namespace_test.go b/kubernetes/resource_kubernetes_namespace_test.go deleted file mode 100644 index 0b504ed4e5..0000000000 --- a/kubernetes/resource_kubernetes_namespace_test.go +++ /dev/null @@ -1,432 +0,0 @@ -package kubernetes - -import ( - "fmt" - "reflect" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesNamespace_basic(t *testing.T) { - var conf api.Namespace - nsName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_namespace.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_basic(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "0"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - { - Config: testAccKubernetesNamespaceConfig_addAnnotations(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "0"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - { - Config: testAccKubernetesNamespaceConfig_addLabels(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - { - Config: testAccKubernetesNamespaceConfig_smallerLists(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.Different", "1234"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "Different": "1234"}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "2"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - { - Config: testAccKubernetesNamespaceConfig_noLists(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesNamespace_invalidLabelValueType(t *testing.T) { - nsName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_invalidLabelValueType(nsName), - ExpectError: regexp.MustCompile("Expected value to be string"), - }, - }, - }) -} - -func TestAccKubernetesNamespace_importBasic(t *testing.T) { - resourceName := "kubernetes_namespace.test" - nsName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_basic(nsName), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesNamespace_generatedName(t *testing.T) { - var conf api.Namespace - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_namespace.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_namespace.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesNamespace_withSpecialCharacters(t *testing.T) { - var conf api.Namespace - nsName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_namespace.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_specialCharacters(nsName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesNamespaceExists("kubernetes_namespace.test", &conf), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.%", "2"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{ - "myhost.co.uk/any-path": "one", - "Different": "1234", - }), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.myhost.co.uk/any-path", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.annotations.Different", "1234"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.%", "2"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{ - "myhost.co.uk/any-path": "one", - "TestLabelThree": "three", - }), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.myhost.co.uk/any-path", "one"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.labels.TestLabelThree", "three"), - resource.TestCheckResourceAttr("kubernetes_namespace.test", "metadata.0.name", nsName), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_namespace.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesNamespace_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_namespace.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesNamespaceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesNamespaceConfig_generatedName(prefix), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func testAccCheckMetaAnnotations(om *meta_v1.ObjectMeta, expected map[string]string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(om.Annotations) == 0 { - return nil - } - - // Remove any internal k8s annotations unless we expect them - annotations := om.Annotations - for key, _ := range annotations { - _, isExpected := expected[key] - if isInternalKey(key) && !isExpected { - delete(annotations, key) - } - } - - if !reflect.DeepEqual(annotations, expected) { - return fmt.Errorf("%s annotations don't match.\nExpected: %q\nGiven: %q", - om.Name, expected, om.Annotations) - } - return nil - } -} - -func testAccCheckMetaLabels(om *meta_v1.ObjectMeta, expected map[string]string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(om.Labels) == 0 { - return nil - } - - // Remove any internal k8s labels unless we expect them - labels := om.Labels - for key, _ := range labels { - _, isExpected := expected[key] - if isInternalKey(key) && !isExpected { - delete(labels, key) - } - } - - if !reflect.DeepEqual(labels, expected) { - return fmt.Errorf("%s labels don't match.\nExpected: %q\nGiven: %q", - om.Name, expected, om.Labels) - } - return nil - } -} - -func testAccCheckKubernetesNamespaceDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_namespace" { - continue - } - - resp, err := conn.CoreV1().Namespaces().Get(rs.Primary.ID, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Namespace still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesNamespaceExists(n string, obj *api.Namespace) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - out, err := conn.CoreV1().Namespaces().Get(rs.Primary.ID, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesNamespaceConfig_basic(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - name = "%s" - } -}`, nsName) -} - -func testAccKubernetesNamespaceConfig_addAnnotations(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - name = "%s" - } -}`, nsName) -} -func testAccKubernetesNamespaceConfig_addLabels(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } -}`, nsName) -} - -func testAccKubernetesNamespaceConfig_smallerLists(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } -}`, nsName) -} - -func testAccKubernetesNamespaceConfig_noLists(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - name = "%s" - } -}`, nsName) -} - -func testAccKubernetesNamespaceConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - generate_name = "%s" - } -}`, prefix) -} - -func testAccKubernetesNamespaceConfig_specialCharacters(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - annotations { - "myhost.co.uk/any-path" = "one" - "Different" = "1234" - } - labels { - "myhost.co.uk/any-path" = "one" - "TestLabelThree" = "three" - } - - name = "%s" - } -}`, nsName) -} - -func testAccKubernetesNamespaceConfig_invalidLabelValueType(nsName string) string { - return fmt.Sprintf(` -resource "kubernetes_namespace" "test" { - metadata { - labels { - "first" = "one" - "integer" = 2 - "bool" = true - } - name = "%s" - } -}`, nsName) -} diff --git a/kubernetes/resource_kubernetes_persistent_volume.go b/kubernetes/resource_kubernetes_persistent_volume.go deleted file mode 100644 index 4e78eaa211..0000000000 --- a/kubernetes/resource_kubernetes_persistent_volume.go +++ /dev/null @@ -1,240 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - gversion "github.com/hashicorp/go-version" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesPersistentVolume() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesPersistentVolumeCreate, - Read: resourceKubernetesPersistentVolumeRead, - Exists: resourceKubernetesPersistentVolumeExists, - Update: resourceKubernetesPersistentVolumeUpdate, - Delete: resourceKubernetesPersistentVolumeDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - CustomizeDiff: func(diff *schema.ResourceDiff, meta interface{}) error { - if diff.Id() == "" { - // We only care about updates, not creation - return nil - } - - // Mutation of PersistentVolumeSource after creation is no longer allowed in 1.9+ - // See https://github.com/kubernetes/kubernetes/blob/v1.9.3/CHANGELOG-1.9.md#storage-3 - conn := meta.(*kubernetes.Clientset) - serverVersion, err := conn.ServerVersion() - if err != nil { - return err - } - - k8sVersion, err := gversion.NewVersion(serverVersion.String()) - if err != nil { - return err - } - - v1_9_0, _ := gversion.NewVersion("1.9.0") - if k8sVersion.Equal(v1_9_0) || k8sVersion.GreaterThan(v1_9_0) { - if diff.HasChange("spec.0.persistent_volume_source") { - keys := diff.GetChangedKeysPrefix("spec.0.persistent_volume_source") - for _, key := range keys { - if diff.HasChange(key) { - err := diff.ForceNew(key) - if err != nil { - return err - } - } - } - return nil - } - } - - return nil - }, - - Schema: map[string]*schema.Schema{ - "metadata": metadataSchema("persistent volume", false), - "spec": { - Type: schema.TypeList, - Description: "Spec of the persistent volume owned by the cluster", - Required: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "access_modes": { - Type: schema.TypeSet, - Description: "Contains all ways the volume can be mounted. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes", - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "capacity": { - Type: schema.TypeMap, - Description: "A description of the persistent volume's resources and capacity. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#capacity", - Required: true, - Elem: schema.TypeString, - ValidateFunc: validateResourceList, - }, - "persistent_volume_reclaim_policy": { - Type: schema.TypeString, - Description: "What happens to a persistent volume when released from its claim. Valid options are Retain (default) and Recycle. Recycling must be supported by the volume plugin underlying this persistent volume. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#recycling-policy", - Optional: true, - Default: "Retain", - }, - "persistent_volume_source": { - Type: schema.TypeList, - Description: "The specification of a persistent volume.", - Required: true, - MaxItems: 1, - Elem: persistentVolumeSourceSchema(), - }, - "storage_class_name": { - Type: schema.TypeString, - Description: "A description of the persistent volume's class. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class", - Optional: true, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesPersistentVolumeCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandPersistentVolumeSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - volume := api.PersistentVolume{ - ObjectMeta: metadata, - Spec: spec, - } - - log.Printf("[INFO] Creating new persistent volume: %#v", volume) - out, err := conn.CoreV1().PersistentVolumes().Create(&volume) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new persistent volume: %#v", out) - - stateConf := &resource.StateChangeConf{ - Target: []string{"Available", "Bound"}, - Pending: []string{"Pending"}, - Timeout: 5 * time.Minute, - Refresh: func() (interface{}, string, error) { - out, err := conn.CoreV1().PersistentVolumes().Get(metadata.Name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[ERROR] Received error: %#v", err) - return out, "Error", err - } - - statusPhase := fmt.Sprintf("%v", out.Status.Phase) - log.Printf("[DEBUG] Persistent volume %s status received: %#v", out.Name, statusPhase) - return out, statusPhase, nil - }, - } - _, err = stateConf.WaitForState() - if err != nil { - return err - } - log.Printf("[INFO] Persistent volume %s created", out.Name) - - d.SetId(out.Name) - - return resourceKubernetesPersistentVolumeRead(d, meta) -} - -func resourceKubernetesPersistentVolumeRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Reading persistent volume %s", name) - volume, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received persistent volume: %#v", volume) - err = d.Set("metadata", flattenMetadata(volume.ObjectMeta)) - if err != nil { - return err - } - err = d.Set("spec", flattenPersistentVolumeSpec(volume.Spec)) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesPersistentVolumeUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("spec") { - specOps, err := patchPersistentVolumeSpec("/spec", "spec", d) - if err != nil { - return err - } - ops = append(ops, specOps...) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - - log.Printf("[INFO] Updating persistent volume %s: %s", d.Id(), ops) - out, err := conn.CoreV1().PersistentVolumes().Patch(d.Id(), pkgApi.JSONPatchType, data) - if err != nil { - return err - } - log.Printf("[INFO] Submitted updated persistent volume: %#v", out) - d.SetId(out.Name) - - return resourceKubernetesPersistentVolumeRead(d, meta) -} - -func resourceKubernetesPersistentVolumeDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Deleting persistent volume: %#v", name) - err := conn.CoreV1().PersistentVolumes().Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Persistent volume %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesPersistentVolumeExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Checking persistent volume %s", name) - _, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_persistent_volume_claim.go b/kubernetes/resource_kubernetes_persistent_volume_claim.go deleted file mode 100644 index 52807d19f3..0000000000 --- a/kubernetes/resource_kubernetes_persistent_volume_claim.go +++ /dev/null @@ -1,270 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesPersistentVolumeClaim() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesPersistentVolumeClaimCreate, - Read: resourceKubernetesPersistentVolumeClaimRead, - Exists: resourceKubernetesPersistentVolumeClaimExists, - Update: resourceKubernetesPersistentVolumeClaimUpdate, - Delete: resourceKubernetesPersistentVolumeClaimDelete, - Importer: &schema.ResourceImporter{ - State: func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { - d.Set("wait_until_bound", true) - return []*schema.ResourceData{d}, nil - }, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(5 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("persistent volume claim", true), - "spec": { - Type: schema.TypeList, - Description: "Spec defines the desired characteristics of a volume requested by a pod author. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#persistentvolumeclaims", - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "access_modes": { - Type: schema.TypeSet, - Description: "A set of the desired access modes the volume should have. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes-1", - Required: true, - ForceNew: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "resources": { - Type: schema.TypeList, - Description: "A list of the minimum resources the volume should have. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#resources", - Required: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "limits": { - Type: schema.TypeMap, - Description: "Map describing the maximum amount of compute resources allowed. More info: http://kubernetes.io/docs/user-guide/compute-resources/", - Optional: true, - ForceNew: true, - }, - "requests": { - Type: schema.TypeMap, - Description: "Map describing the minimum amount of compute resources required. If this is omitted for a container, it defaults to `limits` if that is explicitly specified, otherwise to an implementation-defined value. More info: http://kubernetes.io/docs/user-guide/compute-resources/", - Optional: true, - ForceNew: true, - }, - }, - }, - }, - "selector": { - Type: schema.TypeList, - Description: "A label query over volumes to consider for binding.", - Optional: true, - ForceNew: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: labelSelectorFields(), - }, - }, - "volume_name": { - Type: schema.TypeString, - Description: "The binding reference to the PersistentVolume backing this claim.", - Optional: true, - ForceNew: true, - Computed: true, - }, - "storage_class_name": { - Type: schema.TypeString, - Description: "Name of the storage class requested by the claim", - Optional: true, - Computed: true, - ForceNew: true, - }, - }, - }, - }, - "wait_until_bound": { - Type: schema.TypeBool, - Description: "Whether to wait for the claim to reach `Bound` state (to find volume in which to claim the space)", - Optional: true, - Default: true, - }, - }, - } -} - -func resourceKubernetesPersistentVolumeClaimCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandPersistentVolumeClaimSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - - claim := api.PersistentVolumeClaim{ - ObjectMeta: metadata, - Spec: spec, - } - - log.Printf("[INFO] Creating new persistent volume claim: %#v", claim) - out, err := conn.CoreV1().PersistentVolumeClaims(metadata.Namespace).Create(&claim) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new persistent volume claim: %#v", out) - - d.SetId(buildId(out.ObjectMeta)) - name := out.ObjectMeta.Name - - if d.Get("wait_until_bound").(bool) { - stateConf := &resource.StateChangeConf{ - Target: []string{"Bound"}, - Pending: []string{"Pending"}, - Timeout: d.Timeout(schema.TimeoutCreate), - Refresh: func() (interface{}, string, error) { - out, err := conn.CoreV1().PersistentVolumeClaims(metadata.Namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[ERROR] Received error: %#v", err) - return out, "", err - } - - statusPhase := fmt.Sprintf("%v", out.Status.Phase) - log.Printf("[DEBUG] Persistent volume claim %s status received: %#v", out.Name, statusPhase) - return out, statusPhase, nil - }, - } - _, err = stateConf.WaitForState() - if err != nil { - var lastWarnings []api.Event - var wErr error - - lastWarnings, wErr = getLastWarningsForObject(conn, out.ObjectMeta, "PersistentVolumeClaim", 3) - if wErr != nil { - return wErr - } - - if len(lastWarnings) == 0 { - lastWarnings, wErr = getLastWarningsForObject(conn, meta_v1.ObjectMeta{ - Name: out.Spec.VolumeName, - }, "PersistentVolume", 3) - if wErr != nil { - return wErr - } - } - - return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings)) - } - } - log.Printf("[INFO] Persistent volume claim %s created", out.Name) - - return resourceKubernetesPersistentVolumeClaimRead(d, meta) -} - -func resourceKubernetesPersistentVolumeClaimRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading persistent volume claim %s", name) - claim, err := conn.CoreV1().PersistentVolumeClaims(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received persistent volume claim: %#v", claim) - err = d.Set("metadata", flattenMetadata(claim.ObjectMeta)) - if err != nil { - return err - } - err = d.Set("spec", flattenPersistentVolumeClaimSpec(claim.Spec)) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesPersistentVolumeClaimUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - // The whole spec is ForceNew = nothing to update there - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - - log.Printf("[INFO] Updating persistent volume claim: %s", ops) - out, err := conn.CoreV1().PersistentVolumeClaims(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return err - } - log.Printf("[INFO] Submitted updated persistent volume claim: %#v", out) - - return resourceKubernetesPersistentVolumeClaimRead(d, meta) -} - -func resourceKubernetesPersistentVolumeClaimDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting persistent volume claim: %#v", name) - err = conn.CoreV1().PersistentVolumeClaims(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Persistent volume claim %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesPersistentVolumeClaimExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking persistent volume claim %s", name) - _, err = conn.CoreV1().PersistentVolumeClaims(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_persistent_volume_claim_test.go b/kubernetes/resource_kubernetes_persistent_volume_claim_test.go deleted file mode 100644 index 0eb51b4e99..0000000000 --- a/kubernetes/resource_kubernetes_persistent_volume_claim_test.go +++ /dev/null @@ -1,924 +0,0 @@ -package kubernetes - -import ( - "fmt" - "os" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - storageapi "k8s.io/api/storage/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesPersistentVolumeClaim_basic(t *testing.T) { - var conf api.PersistentVolumeClaim - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_persistent_volume_claim.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeClaimConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelThree", "three"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelFour", "four"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three", "TestLabelFour": "four"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - ), - }, - { // GKE specific check - Config: testAccKubernetesPersistentVolumeClaimConfig_basic(name), - SkipFunc: func() (bool, error) { - isInGke, err := isRunningInGke() - return !isInGke, err - }, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{ - "TestAnnotationOne": "one", - "volume.beta.kubernetes.io/storage-provisioner": "kubernetes.io/gce-pd", - }), - ), - }, - { // minikube specific check - Config: testAccKubernetesPersistentVolumeClaimConfig_basic(name), - SkipFunc: func() (bool, error) { - isInMinikube, err := isRunningInMinikube() - return !isInMinikube, err - }, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{ - "TestAnnotationOne": "one", - "volume.beta.kubernetes.io/storage-provisioner": "k8s.io/minikube-hostpath", - }), - ), - }, - { - Config: testAccKubernetesPersistentVolumeClaimConfig_metaModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - ), - }, - { // GKE specific check - Config: testAccKubernetesPersistentVolumeClaimConfig_basic(name), - SkipFunc: func() (bool, error) { - isInGke, err := isRunningInGke() - return !isInGke, err - }, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{ - "TestAnnotationOne": "one", - "TestAnnotationTwo": "two", - "volume.beta.kubernetes.io/storage-provisioner": "kubernetes.io/gce-pd", - }), - ), - }, - { // minikube specific check - Config: testAccKubernetesPersistentVolumeClaimConfig_basic(name), - SkipFunc: func() (bool, error) { - isInMinikube, err := isRunningInMinikube() - return !isInMinikube, err - }, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{ - "TestAnnotationOne": "one", - "TestAnnotationTwo": "two", - "volume.beta.kubernetes.io/storage-provisioner": "k8s.io/minikube-hostpath", - }), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolumeClaim_googleCloud_importBasic(t *testing.T) { - resourceName := "kubernetes_persistent_volume_claim.test" - volumeName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", acctest.RandString(10)) - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeClaimConfig_import(volumeName, claimName, diskName, zone), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesPersistentVolumeClaim_googleCloud_volumeMatch(t *testing.T) { - var pvcConf api.PersistentVolumeClaim - var pvConf api.PersistentVolume - - claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - volumeName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - volumeNameModified := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", acctest.RandString(10)) - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume_claim.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeClaimConfig_volumeMatch(volumeName, claimName, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.volume_name", volumeName), - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &pvConf), - testAccCheckMetaAnnotations(&pvConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bound-by-controller": "yes"}), - ), - }, - { - Config: testAccKubernetesPersistentVolumeClaimConfig_volumeMatch_modified(volumeNameModified, claimName, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.volume_name", volumeNameModified), - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test2", &pvConf), - testAccCheckMetaAnnotations(&pvConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bound-by-controller": "yes"}), - ), - }, - }, - }) -} - -// Label matching isn't supported on GCE -// TODO: Re-enable when we build test env for K8S that supports it - -// func TestAccKubernetesPersistentVolumeClaim_labelsMatch(t *testing.T) { -// var conf api.PersistentVolumeClaim -// claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) -// volumeName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// IDRefreshName: "kubernetes_persistent_volume_claim.test", -// Providers: testAccProviders, -// CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, -// Steps: []resource.TestStep{ -// { -// Config: testAccKubernetesPersistentVolumeClaimConfig_labelsMatch(volumeName, claimName), -// Check: resource.ComposeAggregateTestCheckFunc( -// testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &conf), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), -// testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes", "pv.kubernetes.io/bound-by-controller": "yes"}), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), -// testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_labels.%", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_labels.TfAccTestEnvironment", "blablah"), -// ), -// }, -// }, -// }) -// } - -// func TestAccKubernetesPersistentVolumeClaim_labelsMatchExpression(t *testing.T) { -// var conf api.PersistentVolumeClaim -// claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) -// volumeName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - -// resource.Test(t, resource.TestCase{ -// PreCheck: func() { testAccPreCheck(t) }, -// IDRefreshName: "kubernetes_persistent_volume_claim.test", -// Providers: testAccProviders, -// CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, -// Steps: []resource.TestStep{ -// { -// Config: testAccKubernetesPersistentVolumeClaimConfig_labelsMatchExpression(volumeName, claimName), -// Check: resource.ComposeAggregateTestCheckFunc( -// testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &conf), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), -// testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes", "pv.kubernetes.io/bound-by-controller": "yes"}), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), -// testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), -// resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.#", "1"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.key", "TfAccTestEnvironment"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.operator", "In"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.values.#", "3"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.values.1187371253", "three"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.values.2053932785", "one"), -// resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.selector.0.match_expressions.0.values.298486374", "two"), -// ), -// }, -// }, -// }) -// } - -func TestAccKubernetesPersistentVolumeClaim_googleCloud_volumeUpdate(t *testing.T) { - var pvcConf api.PersistentVolumeClaim - var pvConf api.PersistentVolume - - claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - volumeName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", acctest.RandString(10)) - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume_claim.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeClaimConfig_volumeUpdate(volumeName, claimName, "5Gi", diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.volume_name", volumeName), - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &pvConf), - testAccCheckMetaAnnotations(&pvConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bound-by-controller": "yes"}), - testAccCheckClaimRef(&pvConf, &ObjectRefStatic{Namespace: "default", Name: claimName}), - ), - }, - { - Config: testAccKubernetesPersistentVolumeClaimConfig_volumeUpdate(volumeName, claimName, "10Gi", diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bind-completed": "yes"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.volume_name", volumeName), - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &pvConf), - testAccCheckMetaAnnotations(&pvConf.ObjectMeta, map[string]string{"pv.kubernetes.io/bound-by-controller": "yes"}), - testAccCheckClaimRef(&pvConf, &ObjectRefStatic{Namespace: "default", Name: claimName}), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolumeClaim_googleCloud_storageClass(t *testing.T) { - var pvcConf api.PersistentVolumeClaim - var storageClass storageapi.StorageClass - var secondStorageClass storageapi.StorageClass - - className := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - claimName := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume_claim.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeClaimDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeClaimConfig_storageClass(className, claimName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{ - "pv.kubernetes.io/bind-completed": "yes", - "pv.kubernetes.io/bound-by-controller": "yes", - "volume.beta.kubernetes.io/storage-provisioner": "kubernetes.io/gce-pd", - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.storage_class_name", className), - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &storageClass), - testAccCheckMetaAnnotations(&storageClass.ObjectMeta, map[string]string{}), - ), - }, - { - Config: testAccKubernetesPersistentVolumeClaimConfig_storageClassUpdated(className, claimName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeClaimExists("kubernetes_persistent_volume_claim.test", &pvcConf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&pvcConf.ObjectMeta, map[string]string{ - "pv.kubernetes.io/bind-completed": "yes", - "pv.kubernetes.io/bound-by-controller": "yes", - "volume.beta.kubernetes.io/storage-provisioner": "kubernetes.io/gce-pd", - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&pvcConf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "metadata.0.name", claimName), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume_claim.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.resources.0.requests.storage", "5Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume_claim.test", "spec.0.storage_class_name", className+"-second"), - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &storageClass), - testAccCheckMetaAnnotations(&storageClass.ObjectMeta, map[string]string{}), - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.second", &secondStorageClass), - testAccCheckMetaAnnotations(&secondStorageClass.ObjectMeta, map[string]string{}), - ), - }, - }, - }) -} - -func testAccCheckKubernetesPersistentVolumeClaimDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_persistent_volume_claim" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().PersistentVolumeClaims(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Namespace == namespace && resp.Name == name { - return fmt.Errorf("Persistent Volume still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesPersistentVolumeClaimExists(n string, obj *api.PersistentVolumeClaim) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().PersistentVolumeClaims(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccCheckClaimRef(pv *api.PersistentVolume, expected *ObjectRefStatic) resource.TestCheckFunc { - return func(s *terraform.State) error { - or := pv.Spec.ClaimRef - if or == nil { - return fmt.Errorf("Expected ClaimRef to be not-nil, specifically %#v", *expected) - } - if or.Namespace != expected.Namespace { - return fmt.Errorf("Expected object reference %q, given: %q", expected.Namespace, or.Namespace) - } - if or.Name != expected.Name { - return fmt.Errorf("Expected object reference %q, given: %q", expected.Name, or.Name) - } - return nil - } -} - -type ObjectRefStatic struct { - Namespace string - Name string -} - -func testAccKubernetesPersistentVolumeClaimConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - TestLabelFour = "four" - } - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - resources { - requests { - storage = "5Gi" - } - } - selector { - match_expressions { - key = "environment" - operator = "In" - values = ["non-exists-12345"] - } - } - } - wait_until_bound = false -} -`, name) -} - -func testAccKubernetesPersistentVolumeClaimConfig_metaModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - resources { - requests { - storage = "5Gi" - } - } - selector { - match_expressions { - key = "environment" - operator = "In" - values = ["non-exists-12345"] - } - } - } - wait_until_bound = false -} -`, name) -} - -func testAccKubernetesPersistentVolumeClaimConfig_import(volumeName, claimName, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "10Gi" - } - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - resources { - requests { - storage = "5Gi" - } - } - volume_name = "${kubernetes_persistent_volume.test.metadata.0.name}" - } -} -`, volumeName, diskName, zone, claimName) -} - -func testAccKubernetesPersistentVolumeClaimConfig_volumeMatch(volumeName, claimName, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "10Gi" - } - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - resources { - requests { - storage = "5Gi" - } - } - volume_name = "${kubernetes_persistent_volume.test.metadata.0.name}" - } -} -`, volumeName, diskName, zone, claimName) -} - -func testAccKubernetesPersistentVolumeClaimConfig_volumeMatch_modified(volumeName, claimName, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test2" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "10Gi" - } - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - resources { - requests { - storage = "5Gi" - } - } - volume_name = "${kubernetes_persistent_volume.test2.metadata.0.name}" - } -} -`, volumeName, diskName, zone, claimName) -} - -// func testAccKubernetesPersistentVolumeClaimConfig_labelsMatch(volumeName, claimName string) string { -// return fmt.Sprintf(` -// resource "kubernetes_persistent_volume" "test" { -// metadata { -// labels { -// TfAccTestEnvironment = "blablah" -// } -// name = "%s" -// } -// spec { -// capacity { -// storage = "10Gi" -// } -// access_modes = ["ReadWriteOnce"] -// persistent_volume_source { -// gce_persistent_disk { -// pd_name = "test123" -// } -// } -// } -// } - -// resource "kubernetes_persistent_volume_claim" "test" { -// metadata { -// name = "%s" -// } -// spec { -// access_modes = ["ReadWriteOnce"] -// resources { -// requests { -// storage = "5Gi" -// } -// } -// selector { -// match_labels { -// TfAccTestEnvironment = "blablah" -// } -// } -// } -// } -// `, volumeName, claimName) -// } - -// func testAccKubernetesPersistentVolumeClaimConfig_labelsMatchExpression(volumeName, claimName string) string { -// return fmt.Sprintf(` -// resource "kubernetes_persistent_volume" "test" { -// metadata { -// labels { -// TfAccTestEnvironment = "two" -// } -// name = "%s" -// } -// spec { -// capacity { -// storage = "10Gi" -// } -// access_modes = ["ReadWriteOnce"] -// persistent_volume_source { -// gce_persistent_disk { -// pd_name = "test123" -// } -// } -// } -// } - -// resource "kubernetes_persistent_volume_claim" "test" { -// metadata { -// name = "%s" -// } -// spec { -// access_modes = ["ReadWriteOnce"] -// resources { -// requests { -// storage = "5Gi" -// } -// } -// selector { -// match_expressions { -// key = "TfAccTestEnvironment" -// operator = "In" -// values = ["one", "three", "two"] -// } -// } -// } -// } -// `, volumeName, claimName) -// } - -func testAccKubernetesPersistentVolumeClaimConfig_volumeUpdate(volumeName, claimName, storage, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "%s" - } - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - storage_class_name = "standard" - resources { - requests { - storage = "5Gi" - } - } - volume_name = "${kubernetes_persistent_volume.test.metadata.0.name}" - } -} -`, volumeName, storage, diskName, zone, claimName) -} - -func testAccKubernetesPersistentVolumeClaimConfig_storageClass(className, claimName string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-standard" - } -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - resources { - requests { - storage = "5Gi" - } - } - storage_class_name = "${kubernetes_storage_class.test.metadata.0.name}" - } -} -`, className, claimName) -} - -func testAccKubernetesPersistentVolumeClaimConfig_storageClassUpdated(className, claimName string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-standard" - } -} - -resource "kubernetes_storage_class" "second" { - metadata { - name = "%s-second" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-ssd" - } -} - -resource "kubernetes_persistent_volume_claim" "test" { - metadata { - name = "%s" - } - spec { - access_modes = ["ReadWriteOnce"] - resources { - requests { - storage = "5Gi" - } - } - storage_class_name = "${kubernetes_storage_class.second.metadata.0.name}" - } -} -`, className, className, claimName) -} diff --git a/kubernetes/resource_kubernetes_persistent_volume_test.go b/kubernetes/resource_kubernetes_persistent_volume_test.go deleted file mode 100644 index 117a0fa190..0000000000 --- a/kubernetes/resource_kubernetes_persistent_volume_test.go +++ /dev/null @@ -1,745 +0,0 @@ -package kubernetes - -import ( - "fmt" - "os" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesPersistentVolume_googleCloud_basic(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-%s", randString) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", randString) - - region := os.Getenv("GOOGLE_REGION") - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_googleCloud_basic(name, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{ - "TestLabelOne": "one", - "TestLabelTwo": "two", - "TestLabelThree": "three", - "failure-domain.beta.kubernetes.io/region": region, - "failure-domain.beta.kubernetes.io/zone": zone, - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.0.pd_name", diskName), - ), - }, - { - Config: testAccKubernetesPersistentVolumeConfig_googleCloud_modified(name, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{ - "TestLabelOne": "one", - "TestLabelTwo": "two", - "TestLabelThree": "three", - "failure-domain.beta.kubernetes.io/region": region, - "failure-domain.beta.kubernetes.io/zone": zone, - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "42Mi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.3887104832", "ReadOnlyMany"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.0.fs_type", "ntfs"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.0.pd_name", diskName), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.0.read_only", "true"), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_aws_basic(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-%s", randString) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", randString) - - region := os.Getenv("AWS_DEFAULT_REGION") - zone := os.Getenv("AWS_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoAwsSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_aws_basic(name, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{ - "TestLabelOne": "one", - "TestLabelTwo": "two", - "TestLabelThree": "three", - "failure-domain.beta.kubernetes.io/region": region, - "failure-domain.beta.kubernetes.io/zone": zone, - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.0.volume_id"), - ), - }, - { - Config: testAccKubernetesPersistentVolumeConfig_aws_modified(name, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{ - "TestLabelOne": "one", - "TestLabelTwo": "two", - "TestLabelThree": "three", - "failure-domain.beta.kubernetes.io/region": region, - "failure-domain.beta.kubernetes.io/zone": zone, - }), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "42Mi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.0.volume_id"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.0.fs_type", "io1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.0.partition", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.aws_elastic_block_store.0.read_only", "true"), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_googleCloud_importBasic(t *testing.T) { - resourceName := "kubernetes_persistent_volume.test" - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-import-%s", randString) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", randString) - - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_googleCloud_basic(name, diskName, zone), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_googleCloud_volumeSource(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-%s", randString) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", randString) - - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_googleCloud_volumeSource(name, diskName, zone), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.gce_persistent_disk.0.pd_name"), - ), - }, - { - Config: testAccKubernetesPersistentVolumeConfig_hostPath_volumeSource(name, "/custom/testing/path"), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.0.path", "/custom/testing/path"), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_hostPath_volumeSource(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-%s", randString) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_hostPath_volumeSource(name, "/first/path"), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.0.path", "/first/path"), - ), - }, - { - Config: testAccKubernetesPersistentVolumeConfig_hostPath_volumeSource(name, "/second/path"), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1245328686", "ReadWriteOnce"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.host_path.0.path", "/second/path"), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_cephFsSecretRef(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - name := fmt.Sprintf("tf-acc-test-%s", randString) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_cephFsSecretRef(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "2Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1254135962", "ReadWriteMany"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.0.monitors.#", "2"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.0.monitors.2848821021", "10.16.154.78:6789"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.0.monitors.4263435410", "10.16.154.82:6789"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.0.secret_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.persistent_volume_source.0.ceph_fs.0.secret_ref.0.name", "ceph-secret"), - ), - }, - }, - }) -} - -func TestAccKubernetesPersistentVolume_storageClass(t *testing.T) { - var conf api.PersistentVolume - randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum) - - name := fmt.Sprintf("tf-acc-test-%s", randString) - storageClassName := fmt.Sprintf("tf-acc-test-sc-%s", randString) - secondStorageClassName := fmt.Sprintf("tf-acc-test-sc2-%s", randString) - diskName := fmt.Sprintf("tf-acc-test-disk-%s", randString) - zone := os.Getenv("GOOGLE_ZONE") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoGoogleCloudSettingsFound(t) }, - IDRefreshName: "kubernetes_persistent_volume.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPersistentVolumeDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPersistentVolumeConfig_storageClass(name, diskName, storageClassName, secondStorageClassName, zone, "test"), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1254135962", "ReadWriteMany"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.storage_class_name", storageClassName), - ), - }, - { - Config: testAccKubernetesPersistentVolumeConfig_storageClass(name, diskName, storageClassName, secondStorageClassName, zone, "test2"), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPersistentVolumeExists("kubernetes_persistent_volume.test", &conf), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_persistent_volume.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.%", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.capacity.storage", "123Gi"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.access_modes.1254135962", "ReadWriteMany"), - resource.TestCheckResourceAttr("kubernetes_persistent_volume.test", "spec.0.storage_class_name", secondStorageClassName), - ), - }, - }, - }) -} - -func testAccCheckKubernetesPersistentVolumeDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_persistent_volume" { - continue - } - name := rs.Primary.ID - resp, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Persistent Volume still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesPersistentVolumeExists(n string, obj *api.PersistentVolume) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - name := rs.Primary.ID - out, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesPersistentVolumeConfig_googleCloud_basic(name, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - capacity { - storage = "123Gi" - } - access_modes = ["ReadWriteOnce"] - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} -`, name, diskName, zone) -} - -func testAccKubernetesPersistentVolumeConfig_googleCloud_modified(name, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - capacity { - storage = "42Mi" - } - access_modes = ["ReadWriteOnce", "ReadOnlyMany"] - persistent_volume_source { - gce_persistent_disk { - fs_type = "ntfs" - pd_name = "${google_compute_disk.test.name}" - read_only = true - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 10 -} -`, name, diskName, zone) -} - -func testAccKubernetesPersistentVolumeConfig_googleCloud_volumeSource(name, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "123Gi" - } - access_modes = ["ReadWriteOnce"] - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 12 -} -`, name, diskName, zone) -} - -func testAccKubernetesPersistentVolumeConfig_aws_basic(name, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - capacity { - storage = "123Gi" - } - access_modes = ["ReadWriteOnce"] - persistent_volume_source { - aws_elastic_block_store { - volume_id = "${aws_ebs_volume.test.id}" - } - } - } -} - -resource "aws_ebs_volume" "test" { - availability_zone = "%s" - size = 10 - tags { - Name = "%s" - } -} -`, name, zone, diskName) -} - -func testAccKubernetesPersistentVolumeConfig_aws_modified(name, diskName, zone string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - capacity { - storage = "42Mi" - } - access_modes = ["ReadWriteOnce"] - persistent_volume_source { - aws_elastic_block_store { - volume_id = "${aws_ebs_volume.test.id}" - fs_type = "io1" - partition = 1 - read_only = true - } - } - } -} - -resource "aws_ebs_volume" "test" { - availability_zone = "%s" - size = 10 - tags { - Name = "%s" - } -} -`, name, zone, diskName) -} - -func testAccKubernetesPersistentVolumeConfig_hostPath_volumeSource(name, path string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "123Gi" - } - access_modes = ["ReadWriteOnce"] - persistent_volume_source { - host_path { - path = "%s" - } - } - } -}`, name, path) -} - -func testAccKubernetesPersistentVolumeConfig_cephFsSecretRef(name string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "2Gi" - } - access_modes = ["ReadWriteMany"] - persistent_volume_source { - ceph_fs { - monitors = ["10.16.154.78:6789", "10.16.154.82:6789"] - secret_ref { - name = "ceph-secret" - } - } - } - } -}`, name) -} - -func testAccKubernetesPersistentVolumeConfig_storageClass(name, diskName, storageClassName, storageClassName2, zone, refName string) string { - return fmt.Sprintf(` -resource "kubernetes_persistent_volume" "test" { - metadata { - name = "%s" - } - spec { - capacity { - storage = "123Gi" - } - access_modes = ["ReadWriteMany"] - persistent_volume_source { - gce_persistent_disk { - pd_name = "${google_compute_disk.test.name}" - } - } - storage_class_name = "${kubernetes_storage_class.%s.metadata.0.name}" - } -} - -resource "google_compute_disk" "test" { - name = "%s" - type = "pd-ssd" - zone = "%s" - image = "debian-8-jessie-v20170523" - size = 12 -} - -resource "kubernetes_storage_class" "test" { - metadata { - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-ssd" - } -} - -resource "kubernetes_storage_class" "test2" { - metadata { - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-standard" - } -} -`, name, refName, diskName, zone, storageClassName, storageClassName2) -} diff --git a/kubernetes/resource_kubernetes_pod.go b/kubernetes/resource_kubernetes_pod.go deleted file mode 100644 index b51fb11de8..0000000000 --- a/kubernetes/resource_kubernetes_pod.go +++ /dev/null @@ -1,223 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesPod() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesPodCreate, - Read: resourceKubernetesPodRead, - Update: resourceKubernetesPodUpdate, - Delete: resourceKubernetesPodDelete, - Exists: resourceKubernetesPodExists, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(5 * time.Minute), - Delete: schema.DefaultTimeout(5 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("pod", true), - "spec": { - Type: schema.TypeList, - Description: "Specification of the desired behavior of the pod.", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: podSpecFields(false), - }, - }, - }, - } -} -func resourceKubernetesPodCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandPodSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - - spec.AutomountServiceAccountToken = ptrToBool(false) - - pod := api.Pod{ - ObjectMeta: metadata, - Spec: spec, - } - - log.Printf("[INFO] Creating new pod: %#v", pod) - out, err := conn.CoreV1().Pods(metadata.Namespace).Create(&pod) - - if err != nil { - return err - } - log.Printf("[INFO] Submitted new pod: %#v", out) - - d.SetId(buildId(out.ObjectMeta)) - - stateConf := &resource.StateChangeConf{ - Target: []string{"Running"}, - Pending: []string{"Pending"}, - Timeout: d.Timeout(schema.TimeoutCreate), - Refresh: func() (interface{}, string, error) { - out, err := conn.CoreV1().Pods(metadata.Namespace).Get(metadata.Name, metav1.GetOptions{}) - if err != nil { - log.Printf("[ERROR] Received error: %#v", err) - return out, "Error", err - } - - statusPhase := fmt.Sprintf("%v", out.Status.Phase) - log.Printf("[DEBUG] Pods %s status received: %#v", out.Name, statusPhase) - return out, statusPhase, nil - }, - } - _, err = stateConf.WaitForState() - if err != nil { - lastWarnings, wErr := getLastWarningsForObject(conn, out.ObjectMeta, "Pod", 3) - if wErr != nil { - return wErr - } - return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings)) - } - log.Printf("[INFO] Pod %s created", out.Name) - - return resourceKubernetesPodRead(d, meta) -} - -func resourceKubernetesPodUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("spec") { - specOps, err := patchPodSpec("/spec", "spec.0.", d) - if err != nil { - return err - } - ops = append(ops, specOps...) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - - log.Printf("[INFO] Updating pod %s: %s", d.Id(), ops) - - out, err := conn.CoreV1().Pods(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return err - } - log.Printf("[INFO] Submitted updated pod: %#v", out) - - d.SetId(buildId(out.ObjectMeta)) - return resourceKubernetesPodRead(d, meta) -} - -func resourceKubernetesPodRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading pod %s", name) - pod, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received pod: %#v", pod) - - err = d.Set("metadata", flattenMetadata(pod.ObjectMeta)) - if err != nil { - return err - } - - podSpec, err := flattenPodSpec(pod.Spec) - if err != nil { - return err - } - - err = d.Set("spec", podSpec) - if err != nil { - return err - } - return nil - -} - -func resourceKubernetesPodDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting pod: %#v", name) - err = conn.CoreV1().Pods(namespace).Delete(name, nil) - if err != nil { - return err - } - - err = resource.Retry(d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { - out, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return nil - } - return resource.NonRetryableError(err) - } - - log.Printf("[DEBUG] Current state of pod: %#v", out.Status.Phase) - e := fmt.Errorf("Pod %s still exists (%s)", name, out.Status.Phase) - return resource.RetryableError(e) - }) - if err != nil { - return err - } - - log.Printf("[INFO] Pod %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesPodExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking pod %s", name) - _, err = conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_pod_test.go b/kubernetes/resource_kubernetes_pod_test.go deleted file mode 100644 index 45ec541965..0000000000 --- a/kubernetes/resource_kubernetes_pod_test.go +++ /dev/null @@ -1,1266 +0,0 @@ -package kubernetes - -import ( - "fmt" - "os" - "testing" - - api "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" -) - -func TestAccKubernetesPod_basic(t *testing.T) { - var conf1 api.Pod - var conf2 api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - configMapName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName1 := "nginx:1.7.9" - imageName2 := "nginx:1.11" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigBasic(secretName, configMapName, podName, imageName1), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf1), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.%", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.app", "pod_label"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.value_from.0.secret_key_ref.0.name", secretName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.1.value_from.0.config_map_key_ref.0.name", configMapName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.0.name", fmt.Sprintf("%s-from", configMapName)), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.config_map_ref.0.optional", "true"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.0.prefix", "FROM_CM_"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.0.name", fmt.Sprintf("%s-from", secretName)), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.secret_ref.0.optional", "false"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env_from.1.prefix", "FROM_S_"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName1), - ), - }, - { - Config: testAccKubernetesPodConfigBasic(secretName, configMapName, podName, imageName2), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf2), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName2), - testAccCheckKubernetesPodForceNew(&conf1, &conf2, false), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_initContainer_updateForcesNew(t *testing.T) { - var conf1 api.Pod - var conf2 api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - image1 := "busybox:1.27" - image2 := "busybox:1.28" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithInitContainer(podName, image1), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf1), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.%", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.app", "pod_label"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.name", "install"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.image", image1), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.0", "wget"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.1", "-O"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.2", "/work-dir/index.html"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.3", "http://kubernetes.io"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.volume_mount.0.name", "workdir"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.volume_mount.0.mount_path", "/work-dir"), - ), - }, - { - Config: testAccKubernetesPodConfigWithInitContainer(podName, image2), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf2), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.%", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.labels.app", "pod_label"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.name", "install"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.image", image2), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.0", "wget"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.1", "-O"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.2", "/work-dir/index.html"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.command.3", "http://kubernetes.io"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.volume_mount.0.name", "workdir"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.init_container.0.volume_mount.0.mount_path", "/work-dir"), - testAccCheckKubernetesPodForceNew(&conf1, &conf2, true), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_updateArgsForceNew(t *testing.T) { - var conf1 api.Pod - var conf2 api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "hashicorp/http-echo:latest" - argsBefore := `["-listen=:80", "-text='before modification'"]` - argsAfter := `["-listen=:80", "-text='after modification'"]` - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigArgsUpdate(podName, imageName, argsBefore), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf1), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.0", "-listen=:80"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.1", "-text='before modification'"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.name", "containername"), - ), - }, - { - Config: testAccKubernetesPodConfigArgsUpdate(podName, imageName, argsAfter), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf2), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.0", "-listen=:80"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.1", "-text='after modification'"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.name", "containername"), - testAccCheckKubernetesPodForceNew(&conf1, &conf2, true), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_updateEnvForceNew(t *testing.T) { - var conf1 api.Pod - var conf2 api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "hashicorp/http-echo:latest" - envBefore := "bar" - envAfter := "baz" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigEnvUpdate(podName, imageName, envBefore), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf1), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.name", "foo"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.value", "bar"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.name", "containername"), - ), - }, - { - Config: testAccKubernetesPodConfigEnvUpdate(podName, imageName, envAfter), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf2), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "metadata.0.name", podName), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_pod.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.name", "foo"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.env.0.value", "baz"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.name", "containername"), - testAccCheckKubernetesPodForceNew(&conf1, &conf2, true), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_importBasic(t *testing.T) { - resourceName := "kubernetes_pod.test" - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithSecurityContext(podName, imageName), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesPod_with_pod_security_context(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithSecurityContext(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.security_context.0.run_as_non_root", "true"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.security_context.0.run_as_user", "101"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.security_context.0.supplemental_groups.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.security_context.0.supplemental_groups.988695518", "101"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_container_liveness_probe_using_exec(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/busybox" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithLivenessProbeUsingExec(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.#", "3"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.exec.0.command.0", "cat"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.exec.0.command.1", "/tmp/healthy"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.failure_threshold", "3"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.initial_delay_seconds", "5"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_container_liveness_probe_using_http_get(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithLivenessProbeUsingHTTPGet(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.0.path", "/healthz"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.0.port", "8080"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.0.http_header.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.0.http_header.0.name", "X-Custom-Header"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.http_get.0.http_header.0.value", "Awesome"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.initial_delay_seconds", "3"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_container_liveness_probe_using_tcp(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithLivenessProbeUsingTCP(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.tcp_socket.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.liveness_probe.0.tcp_socket.0.port", "8080"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_container_lifecycle(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithLifeCycle(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.post_start.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.post_start.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.0", "ls"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.post_start.0.exec.0.command.1", "-al"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.pre_stop.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.pre_stop.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.0", "date"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_container_security_context(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithContainerSecurityContext(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.privileged", "true"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.run_as_user", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.se_linux_options.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.se_linux_options.0.level", "s0:c123,c456"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.capabilities.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.capabilities.0.add.#", "2"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.capabilities.0.add.0", "NET_ADMIN"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.security_context.0.capabilities.0.add.1", "SYS_TIME"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_volume_mount(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithVolumeMounts(secretName, podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_path", "/tmp/my_path"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "db"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.read_only", "false"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path", ""), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_cfg_map_volume_mount(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - cfgMap := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithConfigMapVolume(cfgMap, podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_path", "/tmp/my_path"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "cfg"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.read_only", "false"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.sub_path", ""), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.name", "cfg"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.config_map.0.name", cfgMap), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.config_map.0.default_mode", "511"), // 0777 in decimal - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_resource_requirements(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithResourceRequirements(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.resources.0.requests.0.memory", "50Mi"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.resources.0.requests.0.cpu", "250m"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.resources.0.limits.0.memory", "512Mi"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.resources.0.limits.0.cpu", "500m"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_empty_dir_volume(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithEmptyDirVolumes(podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.mount_path", "/cache"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.volume_mount.0.name", "cache-volume"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.empty_dir.0.medium", "Memory"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_with_secret_vol_items(t *testing.T) { - var conf api.Pod - - secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigWithSecretItemsVolume(secretName, podName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.secret.0.items.#", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.secret.0.items.0.key", "one"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.volume.0.secret.0.items.0.path", "path/to/one"), - ), - }, - }, - }) -} - -func TestAccKubernetesPod_gke_with_nodeSelector(t *testing.T) { - var conf api.Pod - - podName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - region := os.Getenv("GOOGLE_REGION") - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNotRunningInGke(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesPodDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesPodConfigNodeSelector(podName, imageName, region), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesPodExists("kubernetes_pod.test", &conf), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.node_selector.%", "1"), - resource.TestCheckResourceAttr("kubernetes_pod.test", "spec.0.node_selector.failure-domain.beta.kubernetes.io/region", region), - ), - }, - }, - }) -} - -func testAccCheckKubernetesPodDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_pod" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - if err == nil { - if resp.Namespace == namespace && resp.Name == name { - return fmt.Errorf("Pod still exists: %s: %#v", rs.Primary.ID, resp.Status.Phase) - } - } - } - - return nil -} - -func testAccCheckKubernetesPodExists(n string, obj *api.Pod) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - return err - } - *obj = *out - return nil - } -} - -func testAccCheckKubernetesPodForceNew(old, new *api.Pod, wantNew bool) resource.TestCheckFunc { - return func(s *terraform.State) error { - if wantNew { - if old.ObjectMeta.UID == new.ObjectMeta.UID { - return fmt.Errorf("Expecting new resource for pod %s", old.ObjectMeta.UID) - } - } else { - if old.ObjectMeta.UID != new.ObjectMeta.UID { - return fmt.Errorf("Expecting pod UIDs to be the same: expected %s got %s", old.ObjectMeta.UID, new.ObjectMeta.UID) - } - } - return nil - } -} - -func testAccKubernetesPodConfigBasic(secretName, configMapName, podName, imageName string) string { - return fmt.Sprintf(` - -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - - data { - one = "first" - } -} - -resource "kubernetes_secret" "test_from" { - metadata { - name = "%s-from" - } - - data { - one = "first_from" - second = "second_from" - } -} - -resource "kubernetes_config_map" "test" { - metadata { - name = "%s" - } - - data { - one = "ONE" - } -} - -resource "kubernetes_config_map" "test_from" { - metadata { - name = "%s-from" - } - - data { - one = "ONE_FROM" - two = "TWO_FROM" - } -} - -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - - env = [{ - name = "EXPORTED_VARIBALE_FROM_SECRET" - - value_from { - secret_key_ref { - name = "${kubernetes_secret.test.metadata.0.name}" - key = "one" - } - } - }, - { - name = "EXPORTED_VARIBALE_FROM_CONFIG_MAP" - - value_from { - config_map_key_ref { - name = "${kubernetes_config_map.test.metadata.0.name}" - key = "one" - } - } - }, - ] - - env_from = [{ - config_map_ref { - name = "${kubernetes_config_map.test_from.metadata.0.name}" - optional = true - } - prefix = "FROM_CM_" - }, { - secret_ref { - name = "${kubernetes_secret.test_from.metadata.0.name}" - optional = false - } - prefix = "FROM_S_" - }] - - } - volume { - name = "db" - secret = { - secret_name = "${kubernetes_secret.test.metadata.0.name}" - } - } - } -} - `, secretName, secretName, configMapName, configMapName, podName, imageName) -} - -func testAccKubernetesPodConfigWithInitContainer(podName string, image string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - spec { - container { - name = "nginx" - image = "nginx" - port { - container_port = 80 - } - volume_mount { - name = "workdir" - mount_path = "/usr/share/nginx/html" - } - } - init_container { - name = "install" - image = "%s" - command = ["wget", "-O", "/work-dir/index.html", "http://kubernetes.io"] - volume_mount { - name = "workdir" - mount_path = "/work-dir" - } - } - dns_policy = "Default" - volume { - name = "workdir" - empty_dir {} - } - } -} - `, podName, image) -} - -func testAccKubernetesPodConfigWithSecurityContext(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - spec { - security_context { - run_as_non_root = true - run_as_user = 101 - supplemental_groups = [101] - } - container { - image = "%s" - name = "containername" - } - } -} - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithLivenessProbeUsingExec(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - args = ["/bin/sh", "-c", "touch /tmp/healthy; sleep 300; rm -rf /tmp/healthy; sleep 600"] - - liveness_probe { - exec { - command = ["cat", "/tmp/healthy"] - } - - initial_delay_seconds = 5 - period_seconds = 5 - } - } - } -} - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithLivenessProbeUsingHTTPGet(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - - liveness_probe { - http_get { - path = "/healthz" - port = 8080 - - http_header { - name = "X-Custom-Header" - value = "Awesome" - } - } - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } -} - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithLivenessProbeUsingTCP(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - - liveness_probe { - tcp_socket { - port = 8080 - } - - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } -} - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithLifeCycle(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - spec { - container { - image = "%s" - name = "containername" - args = ["/server"] - - lifecycle { - post_start { - exec { - command = ["ls", "-al"] - } - } - pre_stop { - exec { - command = ["date"] - } - } - } - } - } -} - - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithContainerSecurityContext(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - spec { - container { - image = "%s" - name = "containername" - - security_context { - privileged = true - run_as_user = 1 - se_linux_options { - level = "s0:c123,c456" - } - capabilities { - add = ["NET_ADMIN", "SYS_TIME"] - } - } - } - } -} -`, podName, imageName) -} - -func testAccKubernetesPodConfigWithVolumeMounts(secretName, podName, imageName string) string { - return fmt.Sprintf(` - -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - - data { - one = "first" - } -} - -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/tmp/my_path" - name = "db" - } - } - volume { - name = "db" - secret { - secret_name = "${kubernetes_secret.test.metadata.0.name}" - } - } - } -} - `, secretName, podName, imageName) -} - -func testAccKubernetesPodConfigWithSecretItemsVolume(secretName, podName, imageName string) string { - return fmt.Sprintf(` - -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - - data { - one = "first" - } -} - -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/tmp/my_path" - name = "db" - } - } - volume { - name = "db" - secret { - secret_name = "${kubernetes_secret.test.metadata.0.name}" - items { - key = "one" - path = "path/to/one" - } - } - } - } -} - `, secretName, podName, imageName) -} - -func testAccKubernetesPodConfigWithConfigMapVolume(secretName, podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_config_map" "test" { - metadata { - name = "%s" - } - - data { - one = "first" - } -} - -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/tmp/my_path" - name = "cfg" - } - } - volume { - name = "cfg" - config_map { - name = "${kubernetes_config_map.test.metadata.0.name}" - default_mode = 0777 - } - } - - volume { - name = "cfg-item" - config_map { - name = "${kubernetes_config_map.test.metadata.0.name}" - - items { - key = "one" - path = "one.txt" - } - } - } - - volume { - name = "cfg-item-with-mode" - config_map { - name = "${kubernetes_config_map.test.metadata.0.name}" - - items { - key = "one" - path = "one-with-mode.txt" - mode = "0444" - } - } - } - } -} - `, secretName, podName, imageName) -} - -func testAccKubernetesPodConfigWithResourceRequirements(podName, imageName string) string { - return fmt.Sprintf(` - -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - - resources{ - limits{ - cpu = "0.5" - memory = "512Mi" - } - requests{ - cpu = "250m" - memory = "50Mi" - } - } - - } - } -} - `, podName, imageName) -} - -func testAccKubernetesPodConfigWithEmptyDirVolumes(podName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - labels { - app = "pod_label" - } - - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/cache" - name = "cache-volume" - } - } - volume { - name = "cache-volume" - empty_dir = { - medium = "Memory" - } - } - } -} -`, podName, imageName) -} - -func testAccKubernetesPodConfigNodeSelector(podName, imageName, region string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - } - node_selector { - "failure-domain.beta.kubernetes.io/region" = "%s" - } - } -} -`, podName, imageName, region) -} - -func testAccKubernetesPodConfigArgsUpdate(podName, imageName, args string) string { - return fmt.Sprintf(` -resource "kubernetes_pod" "test" { - metadata { - name = "%s" - } - - spec { - container { - image = "%s" - args = %s - name = "containername" - } - } -} -`, podName, imageName, args) -} - -func testAccKubernetesPodConfigEnvUpdate(podName, imageName, val string) string { - return fmt.Sprintf(` - resource "kubernetes_pod" "test" { - metadata { - name = "%s" - } - - spec { - container { - image = "%s" - name = "containername" - env { - name = "foo" - value = "%s" - } - } - } - } - `, podName, imageName, val) -} diff --git a/kubernetes/resource_kubernetes_replication_controller.go b/kubernetes/resource_kubernetes_replication_controller.go deleted file mode 100644 index f8d3fc3325..0000000000 --- a/kubernetes/resource_kubernetes_replication_controller.go +++ /dev/null @@ -1,272 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesReplicationController() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesReplicationControllerCreate, - Read: resourceKubernetesReplicationControllerRead, - Exists: resourceKubernetesReplicationControllerExists, - Update: resourceKubernetesReplicationControllerUpdate, - Delete: resourceKubernetesReplicationControllerDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Timeouts: &schema.ResourceTimeout{ - Create: schema.DefaultTimeout(10 * time.Minute), - Update: schema.DefaultTimeout(10 * time.Minute), - Delete: schema.DefaultTimeout(10 * time.Minute), - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("replication controller", true), - "spec": { - Type: schema.TypeList, - Description: "Spec defines the specification of the desired behavior of the replication controller. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#spec-and-status", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "min_ready_seconds": { - Type: schema.TypeInt, - Description: "Minimum number of seconds for which a newly created pod should be ready without any of its container crashing, for it to be considered available. Defaults to 0 (pod will be considered available as soon as it is ready)", - Optional: true, - Default: 0, - }, - "replicas": { - Type: schema.TypeInt, - Description: "The number of desired replicas. Defaults to 1. More info: http://kubernetes.io/docs/user-guide/replication-controller#what-is-a-replication-controller", - Optional: true, - Default: 1, - }, - "selector": { - Type: schema.TypeMap, - Description: "A label query over pods that should match the Replicas count. If Selector is empty, it is defaulted to the labels present on the Pod template. Label keys and values that must match in order to be controlled by this replication controller, if empty defaulted to labels on Pod template. More info: http://kubernetes.io/docs/user-guide/labels#label-selectors", - Required: true, - }, - "template": { - Type: schema.TypeList, - Description: "Describes the pod that will be created if insufficient replicas are detected. This takes precedence over a TemplateRef. More info: http://kubernetes.io/docs/user-guide/replication-controller#pod-template", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: podSpecFields(true), - }, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesReplicationControllerCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandReplicationControllerSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - - spec.Template.Spec.AutomountServiceAccountToken = ptrToBool(false) - - rc := api.ReplicationController{ - ObjectMeta: metadata, - Spec: spec, - } - - log.Printf("[INFO] Creating new replication controller: %#v", rc) - out, err := conn.CoreV1().ReplicationControllers(metadata.Namespace).Create(&rc) - if err != nil { - return fmt.Errorf("Failed to create replication controller: %s", err) - } - - d.SetId(buildId(out.ObjectMeta)) - - log.Printf("[DEBUG] Waiting for replication controller %s to schedule %d replicas", - d.Id(), *out.Spec.Replicas) - // 10 mins should be sufficient for scheduling ~10k replicas - err = resource.Retry(d.Timeout(schema.TimeoutCreate), - waitForDesiredReplicasFunc(conn, out.GetNamespace(), out.GetName())) - if err != nil { - return err - } - // We could wait for all pods to actually reach Ready state - // but that means checking each pod status separately (which can be expensive at scale) - // as there's no aggregate data available from the API - - log.Printf("[INFO] Submitted new replication controller: %#v", out) - - return resourceKubernetesReplicationControllerRead(d, meta) -} - -func resourceKubernetesReplicationControllerRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading replication controller %s", name) - rc, err := conn.CoreV1().ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received replication controller: %#v", rc) - - err = d.Set("metadata", flattenMetadata(rc.ObjectMeta)) - if err != nil { - return err - } - - spec, err := flattenReplicationControllerSpec(rc.Spec) - if err != nil { - return err - } - - err = d.Set("spec", spec) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesReplicationControllerUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - - if d.HasChange("spec") { - spec, err := expandReplicationControllerSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - - ops = append(ops, &ReplaceOperation{ - Path: "/spec", - Value: spec, - }) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating replication controller %q: %v", name, string(data)) - out, err := conn.CoreV1().ReplicationControllers(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update replication controller: %s", err) - } - log.Printf("[INFO] Submitted updated replication controller: %#v", out) - - err = resource.Retry(d.Timeout(schema.TimeoutUpdate), - waitForDesiredReplicasFunc(conn, namespace, name)) - if err != nil { - return err - } - - return resourceKubernetesReplicationControllerRead(d, meta) -} - -func resourceKubernetesReplicationControllerDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting replication controller: %#v", name) - - // Drain all replicas before deleting - var ops PatchOperations - ops = append(ops, &ReplaceOperation{ - Path: "/spec/replicas", - Value: 0, - }) - data, err := ops.MarshalJSON() - if err != nil { - return err - } - _, err = conn.CoreV1().ReplicationControllers(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return err - } - - // Wait until all replicas are gone - err = resource.Retry(d.Timeout(schema.TimeoutDelete), - waitForDesiredReplicasFunc(conn, namespace, name)) - if err != nil { - return err - } - - err = conn.CoreV1().ReplicationControllers(namespace).Delete(name, &metav1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Replication controller %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesReplicationControllerExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking replication controller %s", name) - _, err = conn.CoreV1().ReplicationControllers(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} - -func waitForDesiredReplicasFunc(conn *kubernetes.Clientset, ns, name string) resource.RetryFunc { - return func() *resource.RetryError { - rc, err := conn.CoreV1().ReplicationControllers(ns).Get(name, metav1.GetOptions{}) - if err != nil { - return resource.NonRetryableError(err) - } - - desiredReplicas := *rc.Spec.Replicas - log.Printf("[DEBUG] Current number of labelled replicas of %q: %d (of %d)\n", - rc.GetName(), rc.Status.FullyLabeledReplicas, desiredReplicas) - - if rc.Status.FullyLabeledReplicas == desiredReplicas { - return nil - } - - return resource.RetryableError(fmt.Errorf("Waiting for %d replicas of %q to be scheduled (%d)", - desiredReplicas, rc.GetName(), rc.Status.FullyLabeledReplicas)) - } -} diff --git a/kubernetes/resource_kubernetes_replication_controller_test.go b/kubernetes/resource_kubernetes_replication_controller_test.go deleted file mode 100644 index 05ebdf270e..0000000000 --- a/kubernetes/resource_kubernetes_replication_controller_test.go +++ /dev/null @@ -1,933 +0,0 @@ -package kubernetes - -import ( - "fmt" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesReplicationController_basic(t *testing.T) { - var conf api.ReplicationController - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_replication_controller.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.image", "nginx:1.7.8"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.name", "tf-acc-test"), - ), - }, - { - Config: testAccKubernetesReplicationControllerConfig_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.Different", "1234"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "Different": "1234"}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.%", "2"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.image", "nginx:1.7.9"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.name", "tf-acc-test"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_initContainer(t *testing.T) { - var conf api.ReplicationController - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_replication_controller.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfig_initContainer(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.image", "busybox"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.name", "install"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.command.0", "wget"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.command.1", "-O"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.command.2", "/work-dir/index.html"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.command.3", "http://kubernetes.io"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.volume_mount.0.name", "workdir"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.init_container.0.volume_mount.0.mount_path", "/work-dir"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_importBasic(t *testing.T) { - resourceName := "kubernetes_replication_controller.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfig_basic(name), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesReplicationController_generatedName(t *testing.T) { - var conf api.ReplicationController - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_replication_controller.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.labels.%", "3"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_replication_controller.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_replication_controller.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_replication_controller.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfig_generatedName(prefix), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_security_context(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithSecurityContext(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.security_context.0.run_as_non_root", "true"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.security_context.0.run_as_user", "101"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.security_context.0.supplemental_groups.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.security_context.0.supplemental_groups.988695518", "101"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_container_liveness_probe_using_exec(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/busybox" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingExec(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.args.#", "3"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.exec.0.command.0", "cat"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.exec.0.command.1", "/tmp/healthy"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.failure_threshold", "3"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.initial_delay_seconds", "5"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_container_liveness_probe_using_http_get(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingHTTPGet(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.0.path", "/healthz"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.0.port", "8080"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.0.http_header.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.0.http_header.0.name", "X-Custom-Header"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.http_get.0.http_header.0.value", "Awesome"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.initial_delay_seconds", "3"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_container_liveness_probe_using_tcp(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingTCP(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.args.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.tcp_socket.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.liveness_probe.0.tcp_socket.0.port", "8080"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_container_lifecycle(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "gcr.io/google_containers/liveness" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithLifeCycle(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.post_start.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.post_start.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.post_start.0.exec.0.command.#", "2"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.post_start.0.exec.0.command.0", "ls"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.post_start.0.exec.0.command.1", "-al"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.pre_stop.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.pre_stop.0.exec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.lifecycle.0.pre_stop.0.exec.0.command.0", "date"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_container_security_context(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithContainerSecurityContext(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.security_context.#", "1"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_volume_mount(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - secretName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithVolumeMounts(secretName, rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.mount_path", "/tmp/my_path"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.name", "db"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.read_only", "false"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.sub_path", ""), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_resource_requirements(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithResourceRequirements(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.resources.0.requests.0.memory", "50Mi"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.resources.0.requests.0.cpu", "250m"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.resources.0.limits.0.memory", "512Mi"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.resources.0.limits.0.cpu", "500m"), - ), - }, - }, - }) -} - -func TestAccKubernetesReplicationController_with_empty_dir_volume(t *testing.T) { - var conf api.ReplicationController - - rcName := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - imageName := "nginx:1.7.9" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesReplicationControllerDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesReplicationControllerConfigWithEmptyDirVolumes(rcName, imageName), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesReplicationControllerExists("kubernetes_replication_controller.test", &conf), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.image", imageName), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.#", "1"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.mount_path", "/cache"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.container.0.volume_mount.0.name", "cache-volume"), - resource.TestCheckResourceAttr("kubernetes_replication_controller.test", "spec.0.template.0.volume.0.empty_dir.0.medium", "Memory"), - ), - }, - }, - }) -} - -func testAccCheckKubernetesReplicationControllerDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_replication_controller" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().ReplicationControllers(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Replication Controller still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesReplicationControllerExists(n string, obj *api.ReplicationController) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().ReplicationControllers(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesReplicationControllerConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - replicas = 1000 # This is intentionally high to exercise the waiter - selector { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - template { - container { - image = "nginx:1.7.8" - name = "tf-acc-test" - } - } - } -} -`, name) -} - -func testAccKubernetesReplicationControllerConfig_initContainer(name string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - replicas = 1000 # This is intentionally high to exercise the waiter - selector { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - template { - container { - name = "nginx" - image = "nginx" - port { - container_port = 80 - } - volume_mount { - name = "workdir" - mount_path = "/usr/share/nginx/html" - } - } - init_container { - name = "install" - image = "busybox" - command = ["wget", "-O", "/work-dir/index.html", "http://kubernetes.io"] - volume_mount { - name = "workdir" - mount_path = "/work-dir" - } - } - dns_policy = "Default" - volume { - name = "workdir" - empty_dir {} - } - } - } -}`, name) -} - -func testAccKubernetesReplicationControllerConfig_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - spec { - selector { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - template { - container { - image = "nginx:1.7.9" - name = "tf-acc-test" - } - } - } -}`, name) -} - -func testAccKubernetesReplicationControllerConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - generate_name = "%s" - } - spec { - selector { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - template { - container { - image = "nginx:1.7.9" - name = "tf-acc-test" - } - } - } -}`, prefix) -} - -func testAccKubernetesReplicationControllerConfigWithSecurityContext(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - security_context { - run_as_non_root = true - run_as_user = 101 - supplemental_groups = [101] - } - container { - image = "%s" - name = "containername" - } - } - } -} - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingExec(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - args = ["/bin/sh", "-c", "touch /tmp/healthy; sleep 300; rm -rf /tmp/healthy; sleep 600"] - - liveness_probe { - exec { - command = ["cat", "/tmp/healthy"] - } - - initial_delay_seconds = 5 - period_seconds = 5 - } - } - } - } -} - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingHTTPGet(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - args = ["/server"] - - liveness_probe { - http_get { - path = "/healthz" - port = 8080 - - http_header { - name = "X-Custom-Header" - value = "Awesome" - } - } - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } - } -} - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithLivenessProbeUsingTCP(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - args = ["/server"] - - liveness_probe { - tcp_socket { - port = 8080 - } - - initial_delay_seconds = 3 - period_seconds = 3 - } - } - } - } -} - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithLifeCycle(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - args = ["/server"] - - lifecycle { - post_start { - exec { - command = ["ls", "-al"] - } - } - pre_stop { - exec { - command = ["date"] - } - } - } - } - } - } -} - - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithContainerSecurityContext(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - - security_context { - privileged = true - run_as_user = 1 - se_linux_options { - level = "s0:c123,c456" - } - } - } - } - } -} - - - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithVolumeMounts(secretName, rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - - data { - one = "first" - } -} - -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/tmp/my_path" - name = "db" - } - } - volume { - name = "db" - secret = { - secret_name = "${kubernetes_secret.test.metadata.0.name}" - } - } - } - } -} - `, secretName, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithResourceRequirements(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - - resources{ - limits{ - cpu = "0.5" - memory = "512Mi" - } - requests{ - cpu = "250m" - memory = "50Mi" - } - } - } - } - } -} - `, rcName, imageName) -} - -func testAccKubernetesReplicationControllerConfigWithEmptyDirVolumes(rcName, imageName string) string { - return fmt.Sprintf(` -resource "kubernetes_replication_controller" "test" { - metadata { - name = "%s" - labels { - Test = "TfAcceptanceTest" - } - } - - spec { - selector { - Test = "TfAcceptanceTest" - } - template { - container { - image = "%s" - name = "containername" - volume_mount { - mount_path = "/cache" - name = "cache-volume" - } - } - volume { - name = "cache-volume" - empty_dir = { - medium = "Memory" - } - } - } - } -} -`, rcName, imageName) -} diff --git a/kubernetes/resource_kubernetes_resource_quota.go b/kubernetes/resource_kubernetes_resource_quota.go deleted file mode 100644 index 9ffd2e544d..0000000000 --- a/kubernetes/resource_kubernetes_resource_quota.go +++ /dev/null @@ -1,227 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesResourceQuota() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesResourceQuotaCreate, - Read: resourceKubernetesResourceQuotaRead, - Exists: resourceKubernetesResourceQuotaExists, - Update: resourceKubernetesResourceQuotaUpdate, - Delete: resourceKubernetesResourceQuotaDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("resource quota", true), - "spec": { - Type: schema.TypeList, - Description: "Spec defines the desired quota. https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "hard": { - Type: schema.TypeMap, - Description: "The set of desired hard limits for each named resource. More info: http://releases.k8s.io/HEAD/docs/design/admission_control_resource_quota.md#admissioncontrol-plugin-resourcequota", - Optional: true, - Elem: schema.TypeString, - ValidateFunc: validateResourceList, - }, - "scopes": { - Type: schema.TypeSet, - Description: "A collection of filters that must match each object tracked by a quota. If not specified, the quota matches all objects.", - Optional: true, - ForceNew: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesResourceQuotaCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - spec, err := expandResourceQuotaSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - resQuota := api.ResourceQuota{ - ObjectMeta: metadata, - Spec: spec, - } - log.Printf("[INFO] Creating new resource quota: %#v", resQuota) - out, err := conn.CoreV1().ResourceQuotas(metadata.Namespace).Create(&resQuota) - if err != nil { - return fmt.Errorf("Failed to create resource quota: %s", err) - } - log.Printf("[INFO] Submitted new resource quota: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - err = resource.Retry(1*time.Minute, func() *resource.RetryError { - quota, err := conn.CoreV1().ResourceQuotas(out.Namespace).Get(out.Name, meta_v1.GetOptions{}) - if err != nil { - return resource.NonRetryableError(err) - } - if resourceListEquals(spec.Hard, quota.Status.Hard) { - return nil - } - err = fmt.Errorf("Quotas don't match after creation.\nExpected: %#v\nGiven: %#v", - spec.Hard, quota.Status.Hard) - return resource.RetryableError(err) - }) - if err != nil { - return err - } - - return resourceKubernetesResourceQuotaRead(d, meta) -} - -func resourceKubernetesResourceQuotaRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading resource quota %s", name) - resQuota, err := conn.CoreV1().ResourceQuotas(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received resource quota: %#v", resQuota) - - // This is to work around K8S bug - // See https://github.com/kubernetes/kubernetes/issues/44539 - if resQuota.ObjectMeta.GenerateName == "" { - if v, ok := d.GetOk("metadata.0.generate_name"); ok { - resQuota.ObjectMeta.GenerateName = v.(string) - } - } - - err = d.Set("metadata", flattenMetadata(resQuota.ObjectMeta)) - if err != nil { - return err - } - err = d.Set("spec", flattenResourceQuotaSpec(resQuota.Spec)) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesResourceQuotaUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - var spec api.ResourceQuotaSpec - waitForChangedSpec := false - if d.HasChange("spec") { - var err error - spec, err = expandResourceQuotaSpec(d.Get("spec").([]interface{})) - if err != nil { - return err - } - ops = append(ops, &ReplaceOperation{ - Path: "/spec", - Value: spec, - }) - waitForChangedSpec = true - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating resource quota %q: %v", name, string(data)) - out, err := conn.CoreV1().ResourceQuotas(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update resource quota: %s", err) - } - log.Printf("[INFO] Submitted updated resource quota: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - if waitForChangedSpec { - err = resource.Retry(1*time.Minute, func() *resource.RetryError { - quota, err := conn.CoreV1().ResourceQuotas(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return resource.NonRetryableError(err) - } - if resourceListEquals(spec.Hard, quota.Status.Hard) { - return nil - } - err = fmt.Errorf("Quotas don't match after update.\nExpected: %#v\nGiven: %#v", - spec.Hard, quota.Status.Hard) - return resource.RetryableError(err) - }) - if err != nil { - return err - } - } - - return resourceKubernetesResourceQuotaRead(d, meta) -} - -func resourceKubernetesResourceQuotaDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting resource quota: %#v", name) - err = conn.CoreV1().ResourceQuotas(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Resource quota %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesResourceQuotaExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking resource quota %s", name) - _, err = conn.CoreV1().ResourceQuotas(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_resource_quota_test.go b/kubernetes/resource_kubernetes_resource_quota_test.go deleted file mode 100644 index 66ab91d0a5..0000000000 --- a/kubernetes/resource_kubernetes_resource_quota_test.go +++ /dev/null @@ -1,364 +0,0 @@ -package kubernetes - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesResourceQuota_basic(t *testing.T) { - var conf api.ResourceQuota - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_resource_quota.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesResourceQuotaDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesResourceQuotaConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.TestAnnotationOne", "one"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one"}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelThree", "three"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelFour", "four"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three", "TestLabelFour": "four"}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "3"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.cpu", "2"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.memory", "2Gi"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "4"), - ), - }, - { - Config: testAccKubernetesResourceQuotaConfig_metaModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "3"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.cpu", "2"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.memory", "2Gi"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "4"), - ), - }, - { - Config: testAccKubernetesResourceQuotaConfig_specModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "4"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.cpu", "4"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.requests.cpu", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.limits.memory", "4Gi"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "10"), - ), - }, - }, - }) -} - -func TestAccKubernetesResourceQuota_generatedName(t *testing.T) { - var conf api.ResourceQuota - prefix := "tf-acc-test-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_resource_quota.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesResourceQuotaDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesResourceQuotaConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.generate_name", prefix), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "10"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.scopes.#", "0"), - ), - }, - }, - }) -} - -func TestAccKubernetesResourceQuota_withScopes(t *testing.T) { - var conf api.ResourceQuota - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_resource_quota.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesResourceQuotaDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesResourceQuotaConfig_withScopes(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "10"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.scopes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.scopes.193563370", "BestEffort"), - ), - }, - { - Config: testAccKubernetesResourceQuotaConfig_withScopesModified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesResourceQuotaExists("kubernetes_resource_quota.test", &conf), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_resource_quota.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.%", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.hard.pods", "10"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.scopes.#", "1"), - resource.TestCheckResourceAttr("kubernetes_resource_quota.test", "spec.0.scopes.3022121741", "NotBestEffort"), - ), - }, - }, - }) -} - -func TestAccKubernetesResourceQuota_importBasic(t *testing.T) { - resourceName := "kubernetes_resource_quota.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesResourceQuotaDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesResourceQuotaConfig_basic(name), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func testAccCheckKubernetesResourceQuotaDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_resource_quota" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().ResourceQuotas(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Namespace == namespace && resp.Name == name { - return fmt.Errorf("Resource Quota still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesResourceQuotaExists(n string, obj *api.ResourceQuota) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().ResourceQuotas(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesResourceQuotaConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - TestLabelFour = "four" - } - name = "%s" - } - spec { - hard { - "limits.cpu" = 2 - "limits.memory" = "2Gi" - pods = 4 - } - } -} -`, name) -} - -func testAccKubernetesResourceQuotaConfig_metaModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - hard { - "limits.cpu" = 2 - "limits.memory" = "2Gi" - pods = 4 - } - } -} -`, name) -} - -func testAccKubernetesResourceQuotaConfig_specModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - name = "%s" - } - spec { - hard { - "limits.cpu" = 4 - "requests.cpu" = 1 - "limits.memory" = "4Gi" - pods = 10 - } - } -} -`, name) -} - -func testAccKubernetesResourceQuotaConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - generate_name = "%s" - } - spec { - hard { - pods = 10 - } - } -} -`, prefix) -} - -func testAccKubernetesResourceQuotaConfig_withScopes(name string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - name = "%s" - } - spec { - hard { - pods = 10 - } - scopes = ["BestEffort"] - } -} -`, name) -} - -func testAccKubernetesResourceQuotaConfig_withScopesModified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_resource_quota" "test" { - metadata { - name = "%s" - } - spec { - hard { - pods = 10 - } - scopes = ["NotBestEffort"] - } -} -`, name) -} diff --git a/kubernetes/resource_kubernetes_secret.go b/kubernetes/resource_kubernetes_secret.go deleted file mode 100644 index 7ae81f0498..0000000000 --- a/kubernetes/resource_kubernetes_secret.go +++ /dev/null @@ -1,173 +0,0 @@ -package kubernetes - -import ( - "log" - - "fmt" - - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesSecret() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesSecretCreate, - Read: resourceKubernetesSecretRead, - Exists: resourceKubernetesSecretExists, - Update: resourceKubernetesSecretUpdate, - Delete: resourceKubernetesSecretDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("secret", true), - "data": { - Type: schema.TypeMap, - Description: "A map of the secret data.", - Optional: true, - Sensitive: true, - }, - "type": { - Type: schema.TypeString, - Description: "Type of secret", - Default: "Opaque", - Optional: true, - ForceNew: true, - }, - }, - } -} - -func resourceKubernetesSecretCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - secret := api.Secret{ - ObjectMeta: metadata, - Data: expandStringMapToByteMap(d.Get("data").(map[string]interface{})), - } - - if v, ok := d.GetOk("type"); ok { - secret.Type = api.SecretType(v.(string)) - } - - log.Printf("[INFO] Creating new secret: %#v", secret) - out, err := conn.CoreV1().Secrets(metadata.Namespace).Create(&secret) - if err != nil { - return err - } - - log.Printf("[INFO] Submitting new secret: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesSecretRead(d, meta) -} - -func resourceKubernetesSecretRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading secret %s", name) - secret, err := conn.CoreV1().Secrets(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Received secret: %#v", secret) - err = d.Set("metadata", flattenMetadata(secret.ObjectMeta)) - if err != nil { - return err - } - - d.Set("data", byteMapToStringMap(secret.Data)) - d.Set("type", secret.Type) - - return nil -} - -func resourceKubernetesSecretUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("data") { - oldV, newV := d.GetChange("data") - - oldV = base64EncodeStringMap(oldV.(map[string]interface{})) - newV = base64EncodeStringMap(newV.(map[string]interface{})) - - diffOps := diffStringMap("/data/", oldV.(map[string]interface{}), newV.(map[string]interface{})) - - ops = append(ops, diffOps...) - } - - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - - log.Printf("[INFO] Updating secret %q: %v", name, data) - out, err := conn.CoreV1().Secrets(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update secret: %s", err) - } - - log.Printf("[INFO] Submitting updated secret: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesSecretRead(d, meta) -} - -func resourceKubernetesSecretDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting secret: %q", name) - err = conn.CoreV1().Secrets(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Secret %s deleted", name) - - d.SetId("") - - return nil -} - -func resourceKubernetesSecretExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking secret %s", name) - _, err = conn.CoreV1().Secrets(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - - return true, err -} diff --git a/kubernetes/resource_kubernetes_secret_test.go b/kubernetes/resource_kubernetes_secret_test.go deleted file mode 100644 index 0b13cafa3c..0000000000 --- a/kubernetes/resource_kubernetes_secret_test.go +++ /dev/null @@ -1,454 +0,0 @@ -package kubernetes - -import ( - "fmt" - "reflect" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesSecret_basic(t *testing.T) { - var conf api.Secret - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_secret.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_emptyData(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "0"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "type", "Opaque"), - ), - }, - { - Config: testAccKubernetesSecretConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.one", "first"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.two", "second"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "type", "Opaque"), - testAccCheckSecretData(&conf, map[string]string{"one": "first", "two": "second"}), - ), - }, - { - Config: testAccKubernetesSecretConfig_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.Different", "1234"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "Different": "1234"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "3"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.one", "first"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.two", "second"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.nine", "ninth"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "type", "Opaque"), - testAccCheckSecretData(&conf, map[string]string{"one": "first", "two": "second", "nine": "ninth"}), - ), - }, - { - Config: testAccKubernetesSecretConfig_noData(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "0"), - testAccCheckSecretData(&conf, map[string]string{}), - ), - }, - { - Config: testAccKubernetesSecretConfig_typeSpecified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.username", "admin"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.password", "password"), - resource.TestCheckResourceAttr("kubernetes_secret.test", "type", "kubernetes.io/basic-auth"), - testAccCheckSecretData(&conf, map[string]string{"username": "admin", "password": "password"}), - ), - }, - }, - }) -} - -func TestAccKuberNetesSecret_dotInName(t *testing.T) { - var conf api.Secret - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_dotInSecretName, - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.name", "dot.test"), - ), - }, - }, - }) -} - -func TestAccKubernetesSecret_importBasic(t *testing.T) { - resourceName := "kubernetes_secret.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_basic(name), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesSecret_generatedName(t *testing.T) { - var conf api.Secret - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_secret.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_secret.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_secret.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_secret.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesSecret_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_secret.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_generatedName(prefix), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesSecret_binaryData(t *testing.T) { - var conf api.Secret - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_secret.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesSecretDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesSecretConfig_binaryData(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "1"), - ), - }, - { - Config: testAccKubernetesSecretConfig_binaryData2(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesSecretExists("kubernetes_secret.test", &conf), - resource.TestCheckResourceAttr("kubernetes_secret.test", "data.%", "2"), - ), - }, - }, - }) -} - -func testAccCheckSecretData(m *api.Secret, expected map[string]string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(m.Data) == 0 { - return nil - } - if !reflect.DeepEqual(byteMapToStringMap(m.Data), expected) { - return fmt.Errorf("%s data don't match.\nExpected: %q\nGiven: %q", - m.Name, expected, m.Data) - } - return nil - } -} - -func testAccCheckKubernetesSecretDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_secret" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().Secrets(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Secret still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesSecretExists(n string, obj *api.Secret) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().Secrets(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -const testAccKubernetesSecretConfig_dotInSecretName = ` -resource "kubernetes_secret" "test" { - metadata { - name = "dot.test" - } - } -` - -func testAccKubernetesSecretConfig_emptyData(name string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - data {} -}`, name) -} - -func testAccKubernetesSecretConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - data { - one = "first" - two = "second" - } -}`, name) -} - -func testAccKubernetesSecretConfig_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - data { - one = "first" - two = "second" - nine = "ninth" - } -}`, name) -} - -func testAccKubernetesSecretConfig_noData(name string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } -}`, name) -} - -func testAccKubernetesSecretConfig_typeSpecified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - name = "%s" - } - data { - username = "admin" - password = "password" - } - type = "kubernetes.io/basic-auth" -}`, name) -} - -func testAccKubernetesSecretConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - generate_name = "%s" - } - data { - one = "first" - two = "second" - } -}`, prefix) -} - -func testAccKubernetesSecretConfig_binaryData(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - generate_name = "%s" - } - data { - one = "${file("./test-fixtures/binary.data")}" - } -}`, prefix) -} - -func testAccKubernetesSecretConfig_binaryData2(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_secret" "test" { - metadata { - generate_name = "%s" - } - data { - one = "${file("./test-fixtures/binary2.data")}" - two = "${file("./test-fixtures/binary.data")}" - } -}`, prefix) -} diff --git a/kubernetes/resource_kubernetes_service.go b/kubernetes/resource_kubernetes_service.go deleted file mode 100644 index 930a7752b9..0000000000 --- a/kubernetes/resource_kubernetes_service.go +++ /dev/null @@ -1,301 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesService() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesServiceCreate, - Read: resourceKubernetesServiceRead, - Exists: resourceKubernetesServiceExists, - Update: resourceKubernetesServiceUpdate, - Delete: resourceKubernetesServiceDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("service", true), - "spec": { - Type: schema.TypeList, - Description: "Spec defines the behavior of a service. https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#spec-and-status", - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cluster_ip": { - Type: schema.TypeString, - Description: "The IP address of the service. It is usually assigned randomly by the master. If an address is specified manually and is not in use by others, it will be allocated to the service; otherwise, creation of the service will fail. `None` can be specified for headless services when proxying is not required. Ignored if type is `ExternalName`. More info: http://kubernetes.io/docs/user-guide/services#virtual-ips-and-service-proxies", - Optional: true, - ForceNew: true, - Computed: true, - }, - "external_ips": { - Type: schema.TypeSet, - Description: "A list of IP addresses for which nodes in the cluster will also accept traffic for this service. These IPs are not managed by Kubernetes. The user is responsible for ensuring that traffic arrives at a node with this IP. A common example is external load-balancers that are not part of the Kubernetes system.", - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "external_name": { - Type: schema.TypeString, - Description: "The external reference that kubedns or equivalent will return as a CNAME record for this service. No proxying will be involved. Must be a valid DNS name and requires `type` to be `ExternalName`.", - Optional: true, - }, - "load_balancer_ip": { - Type: schema.TypeString, - Description: "Only applies to `type = LoadBalancer`. LoadBalancer will get created with the IP specified in this field. This feature depends on whether the underlying cloud-provider supports specifying this field when a load balancer is created. This field will be ignored if the cloud-provider does not support the feature.", - Optional: true, - }, - "load_balancer_source_ranges": { - Type: schema.TypeSet, - Description: "If specified and supported by the platform, this will restrict traffic through the cloud-provider load-balancer will be restricted to the specified client IPs. This field will be ignored if the cloud-provider does not support the feature. More info: http://kubernetes.io/docs/user-guide/services-firewalls", - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "port": { - Type: schema.TypeList, - Description: "The list of ports that are exposed by this service. More info: http://kubernetes.io/docs/user-guide/services#virtual-ips-and-service-proxies", - Optional: true, - MinItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "The name of this port within the service. All ports within the service must have unique names. Optional if only one ServicePort is defined on this service.", - Optional: true, - }, - "node_port": { - Type: schema.TypeInt, - Description: "The port on each node on which this service is exposed when `type` is `NodePort` or `LoadBalancer`. Usually assigned by the system. If specified, it will be allocated to the service if unused or else creation of the service will fail. Default is to auto-allocate a port if the `type` of this service requires one. More info: http://kubernetes.io/docs/user-guide/services#type--nodeport", - Computed: true, - Optional: true, - }, - "port": { - Type: schema.TypeInt, - Description: "The port that will be exposed by this service.", - Required: true, - }, - "protocol": { - Type: schema.TypeString, - Description: "The IP protocol for this port. Supports `TCP` and `UDP`. Default is `TCP`.", - Optional: true, - Default: "TCP", - }, - "target_port": { - Type: schema.TypeString, - Description: "Number or name of the port to access on the pods targeted by the service. Number must be in the range 1 to 65535. This field is ignored for services with `cluster_ip = \"None\"`. More info: http://kubernetes.io/docs/user-guide/services#defining-a-service", - Optional: true, - Computed: true, - }, - }, - }, - }, - "selector": { - Type: schema.TypeMap, - Description: "Route service traffic to pods with label keys and values matching this selector. Only applies to types `ClusterIP`, `NodePort`, and `LoadBalancer`. More info: http://kubernetes.io/docs/user-guide/services#overview", - Optional: true, - }, - "session_affinity": { - Type: schema.TypeString, - Description: "Used to maintain session affinity. Supports `ClientIP` and `None`. Defaults to `None`. More info: http://kubernetes.io/docs/user-guide/services#virtual-ips-and-service-proxies", - Optional: true, - Default: "None", - }, - "type": { - Type: schema.TypeString, - Description: "Determines how the service is exposed. Defaults to `ClusterIP`. Valid options are `ExternalName`, `ClusterIP`, `NodePort`, and `LoadBalancer`. `ExternalName` maps to the specified `external_name`. More info: http://kubernetes.io/docs/user-guide/services#overview", - Optional: true, - Default: "ClusterIP", - }, - }, - }, - }, - "load_balancer_ingress": { - Type: schema.TypeList, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ip": { - Type: schema.TypeString, - Computed: true, - }, - "hostname": { - Type: schema.TypeString, - Computed: true, - }, - }, - }, - }, - }, - } -} - -func resourceKubernetesServiceCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - svc := api.Service{ - ObjectMeta: metadata, - Spec: expandServiceSpec(d.Get("spec").([]interface{})), - } - log.Printf("[INFO] Creating new service: %#v", svc) - out, err := conn.CoreV1().Services(metadata.Namespace).Create(&svc) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new service: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - if out.Spec.Type == api.ServiceTypeLoadBalancer { - log.Printf("[DEBUG] Waiting for load balancer to assign IP/hostname") - - err = resource.Retry(10*time.Minute, func() *resource.RetryError { - svc, err := conn.CoreV1().Services(out.Namespace).Get(out.Name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return resource.NonRetryableError(err) - } - - lbIngress := svc.Status.LoadBalancer.Ingress - - log.Printf("[INFO] Received service status: %#v", svc.Status) - if len(lbIngress) > 0 { - return nil - } - - return resource.RetryableError(fmt.Errorf( - "Waiting for service %q to assign IP/hostname for a load balancer", d.Id())) - }) - if err != nil { - lastWarnings, wErr := getLastWarningsForObject(conn, out.ObjectMeta, "Service", 3) - if wErr != nil { - return wErr - } - return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings)) - } - } - - return resourceKubernetesServiceRead(d, meta) -} - -func resourceKubernetesServiceRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading service %s", name) - svc, err := conn.CoreV1().Services(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received service: %#v", svc) - err = d.Set("metadata", flattenMetadata(svc.ObjectMeta)) - if err != nil { - return err - } - - err = d.Set("load_balancer_ingress", flattenLoadBalancerIngress(svc.Status.LoadBalancer.Ingress)) - if err != nil { - return err - } - - flattened := flattenServiceSpec(svc.Spec) - log.Printf("[DEBUG] Flattened service spec: %#v", flattened) - err = d.Set("spec", flattened) - if err != nil { - return err - } - - return nil -} - -func resourceKubernetesServiceUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("spec") { - serverVersion, err := conn.ServerVersion() - if err != nil { - return err - } - diffOps, err := patchServiceSpec("spec.0.", "/spec/", d, serverVersion) - if err != nil { - return err - } - ops = append(ops, diffOps...) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating service %q: %v", name, string(data)) - out, err := conn.CoreV1().Services(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update service: %s", err) - } - log.Printf("[INFO] Submitted updated service: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesServiceRead(d, meta) -} - -func resourceKubernetesServiceDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting service: %#v", name) - err = conn.CoreV1().Services(namespace).Delete(name, &meta_v1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Service %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesServiceExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking service %s", name) - _, err = conn.CoreV1().Services(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_service_account.go b/kubernetes/resource_kubernetes_service_account.go deleted file mode 100644 index ed6d6cb595..0000000000 --- a/kubernetes/resource_kubernetes_service_account.go +++ /dev/null @@ -1,235 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - "time" - - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesServiceAccount() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesServiceAccountCreate, - Read: resourceKubernetesServiceAccountRead, - Exists: resourceKubernetesServiceAccountExists, - Update: resourceKubernetesServiceAccountUpdate, - Delete: resourceKubernetesServiceAccountDelete, - - // This resource is not importable because the API doesn't offer - // any way to differentiate between default & user-defined secret - // after the account was created. - - Schema: map[string]*schema.Schema{ - "metadata": namespacedMetadataSchema("service account", true), - "image_pull_secret": { - Type: schema.TypeSet, - Description: "A list of references to secrets in the same namespace to use for pulling any images in pods that reference this Service Account. More info: http://kubernetes.io/docs/user-guide/secrets#manually-specifying-an-imagepullsecret", - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - }, - "secret": { - Type: schema.TypeSet, - Description: "A list of secrets allowed to be used by pods running using this Service Account. More info: http://kubernetes.io/docs/user-guide/secrets", - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - }, - "default_secret_name": { - Type: schema.TypeString, - Computed: true, - }, - }, - } -} - -func resourceKubernetesServiceAccountCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - svcAcc := api.ServiceAccount{ - AutomountServiceAccountToken: ptrToBool(false), - ObjectMeta: metadata, - ImagePullSecrets: expandLocalObjectReferenceArray(d.Get("image_pull_secret").(*schema.Set).List()), - Secrets: expandServiceAccountSecrets(d.Get("secret").(*schema.Set).List(), ""), - } - log.Printf("[INFO] Creating new service account: %#v", svcAcc) - out, err := conn.CoreV1().ServiceAccounts(metadata.Namespace).Create(&svcAcc) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new service account: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - // Here we get the only chance to identify and store default secret name - // so we can avoid showing it in diff as it's not managed by Terraform - var resp *api.ServiceAccount - err = resource.Retry(30*time.Second, func() *resource.RetryError { - var err error - resp, err = conn.CoreV1().ServiceAccounts(out.Namespace).Get(out.Name, metav1.GetOptions{}) - if err != nil { - return resource.NonRetryableError(err) - } - if len(resp.Secrets) > len(svcAcc.Secrets) { - return nil - } - return resource.RetryableError(fmt.Errorf("Waiting for default secret of %q to appear", d.Id())) - }) - - diff := diffObjectReferences(svcAcc.Secrets, resp.Secrets) - if len(diff) > 1 { - return fmt.Errorf("Expected 1 generated default secret, %d found: %s", len(diff), diff) - } - - defaultSecret := diff[0] - d.Set("default_secret_name", defaultSecret.Name) - - return resourceKubernetesServiceAccountRead(d, meta) -} - -func diffObjectReferences(origOrs []api.ObjectReference, ors []api.ObjectReference) []api.ObjectReference { - var diff []api.ObjectReference - uniqueRefs := make(map[string]*api.ObjectReference, 0) - for _, or := range origOrs { - uniqueRefs[or.Name] = &or - } - - for _, or := range ors { - _, found := uniqueRefs[or.Name] - if !found { - diff = append(diff, or) - } - } - - return diff -} - -func resourceKubernetesServiceAccountRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Reading service account %s", name) - svcAcc, err := conn.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received service account: %#v", svcAcc) - err = d.Set("metadata", flattenMetadata(svcAcc.ObjectMeta)) - if err != nil { - return err - } - d.Set("image_pull_secret", flattenLocalObjectReferenceArray(svcAcc.ImagePullSecrets)) - - defaultSecretName := d.Get("default_secret_name").(string) - log.Printf("[DEBUG] Default secret name is %q", defaultSecretName) - secrets := flattenServiceAccountSecrets(svcAcc.Secrets, defaultSecretName) - log.Printf("[DEBUG] Flattened secrets: %#v", secrets) - d.Set("secret", secrets) - - return nil -} - -func resourceKubernetesServiceAccountUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - ops := patchMetadata("metadata.0.", "/metadata/", d) - if d.HasChange("image_pull_secret") { - v := d.Get("image_pull_secret").(*schema.Set).List() - ops = append(ops, &ReplaceOperation{ - Path: "/imagePullSecrets", - Value: expandLocalObjectReferenceArray(v), - }) - } - if d.HasChange("secret") { - v := d.Get("secret").(*schema.Set).List() - defaultSecretName := d.Get("default_secret_name").(string) - - ops = append(ops, &ReplaceOperation{ - Path: "/secrets", - Value: expandServiceAccountSecrets(v, defaultSecretName), - }) - } - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating service account %q: %v", name, string(data)) - out, err := conn.CoreV1().ServiceAccounts(namespace).Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update service account: %s", err) - } - log.Printf("[INFO] Submitted updated service account: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesServiceAccountRead(d, meta) -} - -func resourceKubernetesServiceAccountDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return err - } - - log.Printf("[INFO] Deleting service account: %#v", name) - err = conn.CoreV1().ServiceAccounts(namespace).Delete(name, &metav1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Service account %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesServiceAccountExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - namespace, name, err := idParts(d.Id()) - if err != nil { - return false, err - } - - log.Printf("[INFO] Checking service account %s", name) - _, err = conn.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_service_account_test.go b/kubernetes/resource_kubernetes_service_account_test.go deleted file mode 100644 index 16bb56eace..0000000000 --- a/kubernetes/resource_kubernetes_service_account_test.go +++ /dev/null @@ -1,415 +0,0 @@ -package kubernetes - -import ( - "fmt" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesServiceAccount_basic(t *testing.T) { - var conf api.ServiceAccount - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service_account.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceAccountConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceAccountExists("kubernetes_service_account.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "2"), - testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-three$"), - regexp.MustCompile("^" + name + "-four$"), - }), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-one$"), - regexp.MustCompile("^" + name + "-two$"), - regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), - }), - ), - }, - }, - }) -} - -func TestAccKubernetesServiceAccount_update(t *testing.T) { - var conf api.ServiceAccount - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service_account.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceAccountConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceAccountExists("kubernetes_service_account.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "2"), - testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-three$"), - regexp.MustCompile("^" + name + "-four$"), - }), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-one$"), - regexp.MustCompile("^" + name + "-two$"), - regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), - }), - ), - }, - { - Config: testAccKubernetesServiceAccountConfig_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceAccountExists("kubernetes_service_account.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.Different", "1234"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "Different": "1234"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.%", "2"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "3"), - testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-three$"), - regexp.MustCompile("^" + name + "-four$"), - }), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-one$"), - regexp.MustCompile("^" + name + "-two$"), - regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), - }), - ), - }, - { - Config: testAccKubernetesServiceAccountConfig_noAttributes(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceAccountExists("kubernetes_service_account.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.%", "0"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "secret.#", "0"), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "image_pull_secret.#", "0"), - testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + name + "-token-[a-z0-9]+$"), - }), - ), - }, - }, - }) -} - -func TestAccKubernetesServiceAccount_generatedName(t *testing.T) { - var conf api.ServiceAccount - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service_account.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceAccountDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceAccountConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceAccountExists("kubernetes_service_account.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_service_account.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_service_account.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service_account.test", "metadata.0.uid"), - testAccCheckServiceAccountImagePullSecrets(&conf, []*regexp.Regexp{}), - testAccCheckServiceAccountSecrets(&conf, []*regexp.Regexp{ - regexp.MustCompile("^" + prefix + "[a-z0-9]+-token-[a-z0-9]+$"), - }), - ), - }, - }, - }) -} - -func testAccCheckServiceAccountImagePullSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(m.ImagePullSecrets) == 0 { - return nil - } - - if !matchLocalObjectReferenceName(m.ImagePullSecrets, expected) { - return fmt.Errorf("%s image pull secrets don't match.\nExpected: %q\nGiven: %q", - m.Name, expected, m.ImagePullSecrets) - } - - return nil - } -} - -func matchLocalObjectReferenceName(lor []api.LocalObjectReference, expected []*regexp.Regexp) bool { - for _, r := range expected { - for _, ps := range lor { - matched := r.MatchString(ps.Name) - if matched { - return true - } - } - } - return false -} - -func testAccCheckServiceAccountSecrets(m *api.ServiceAccount, expected []*regexp.Regexp) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(m.Secrets) == 0 { - return nil - } - if !matchObjectReferenceName(m.Secrets, expected) { - return fmt.Errorf("%s secrets don't match.\nExpected: %q\nGiven: %q", - m.Name, expected, m.Secrets) - } - return nil - } -} - -func matchObjectReferenceName(lor []api.ObjectReference, expected []*regexp.Regexp) bool { - for _, r := range expected { - for _, ps := range lor { - matched := r.MatchString(ps.Name) - if matched { - return true - } - } - } - return false -} - -func testAccCheckKubernetesServiceAccountDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_service_account" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().ServiceAccounts(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Service Account still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesServiceAccountExists(n string, obj *api.ServiceAccount) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().ServiceAccounts(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesServiceAccountConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service_account" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - secret { - name = "${kubernetes_secret.one.metadata.0.name}" - } - secret { - name = "${kubernetes_secret.two.metadata.0.name}" - } - image_pull_secret { - name = "${kubernetes_secret.three.metadata.0.name}" - } - image_pull_secret { - name = "${kubernetes_secret.four.metadata.0.name}" - } -} - -resource "kubernetes_secret" "one" { - metadata { - name = "%s-one" - } -} - -resource "kubernetes_secret" "two" { - metadata { - name = "%s-two" - } -} - -resource "kubernetes_secret" "three" { - metadata { - name = "%s-three" - } -} - -resource "kubernetes_secret" "four" { - metadata { - name = "%s-four" - } -} -`, name, name, name, name, name) -} - -func testAccKubernetesServiceAccountConfig_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service_account" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - secret { - name = "${kubernetes_secret.one.metadata.0.name}" - } - image_pull_secret { - name = "${kubernetes_secret.two.metadata.0.name}" - } - image_pull_secret { - name = "${kubernetes_secret.three.metadata.0.name}" - } - image_pull_secret { - name = "${kubernetes_secret.four.metadata.0.name}" - } -} - -resource "kubernetes_secret" "one" { - metadata { - name = "%s-one" - } -} - -resource "kubernetes_secret" "two" { - metadata { - name = "%s-two" - } -} - -resource "kubernetes_secret" "three" { - metadata { - name = "%s-three" - } -} - -resource "kubernetes_secret" "four" { - metadata { - name = "%s-four" - } -} -`, name, name, name, name, name) -} - -func testAccKubernetesServiceAccountConfig_noAttributes(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service_account" "test" { - metadata { - name = "%s" - } -}`, name) -} - -func testAccKubernetesServiceAccountConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_service_account" "test" { - metadata { - generate_name = "%s" - } -}`, prefix) -} diff --git a/kubernetes/resource_kubernetes_service_test.go b/kubernetes/resource_kubernetes_service_test.go deleted file mode 100644 index b6eb148363..0000000000 --- a/kubernetes/resource_kubernetes_service_test.go +++ /dev/null @@ -1,685 +0,0 @@ -package kubernetes - -import ( - "fmt" - "reflect" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/core/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesService_basic(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.name", ""), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.node_port", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "8080"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "80"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "None"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "ClusterIP"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Port: int32(8080), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(80), - }, - }), - ), - }, - { - Config: testAccKubernetesServiceConfig_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.name", ""), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.node_port", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "8081"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "80"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "None"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "ClusterIP"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Port: int32(8081), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(80), - }, - }), - ), - }, - }, - }) -} - -func TestAccKubernetesService_loadBalancer(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoLoadBalancersAvailable(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_loadBalancer(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.0.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "8888"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "80"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.1452553500", "10.0.0.4"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.3371212991", "10.0.0.3"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "ext-name-"+name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.138364083", "10.0.0.5/32"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.445311837", "10.0.0.6/32"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.%", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.App", "MyApp"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "ClientIP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "LoadBalancer"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Port: int32(8888), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(80), - }, - }), - ), - }, - { - Config: testAccKubernetesServiceConfig_loadBalancer_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.1452553500", "10.0.0.4"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.563283338", "10.0.0.5"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "ext-name-modified-"+name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.2271073252", "10.0.0.1/32"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.2515041290", "10.0.0.2/32"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.0.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "9999"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "81"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.%", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.App", "MyModifiedApp"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.NewSelector", "NewValue"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "ClientIP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "LoadBalancer"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Port: int32(9999), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(81), - }, - }), - ), - }, - }, - }) -} - -func TestAccKubernetesService_nodePort(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_nodePort(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.1452553500", "10.0.0.4"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.563283338", "10.0.0.5"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "ext-name-"+name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_ip", "12.0.0.125"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.name", "first"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.0.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "10222"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "22"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.name", "second"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.1.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.port", "10333"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.target_port", "33"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.%", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.App", "MyApp"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "ClientIP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "NodePort"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Name: "first", - Port: int32(10222), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(22), - }, - { - Name: "second", - Port: int32(10333), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(33), - }, - }), - ), - }, - }, - }) -} - -func TestAccKubernetesService_noTargetPort(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoLoadBalancersAvailable(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_noTargetPort(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.cluster_ip"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.#", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "2"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.name", "http"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.0.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.port", "80"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.0.target_port", "80"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.name", "https"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "spec.0.port.1.node_port"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.port", "443"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.protocol", "TCP"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.1.target_port", "443"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.%", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.App", "MyOtherApp"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "None"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "LoadBalancer"), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Name: "http", - Port: int32(80), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(80), - }, - { - Name: "https", - Port: int32(443), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromInt(443), - }, - }), - ), - }, - }, - }) -} - -func TestAccKubernetesService_stringTargetPort(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t); skipIfNoLoadBalancersAvailable(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_stringTargetPort(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - testAccCheckServicePorts(&conf, []api.ServicePort{ - { - Port: int32(8080), - Protocol: api.ProtocolTCP, - TargetPort: intstr.FromString("http-server"), - }, - }), - ), - }, - }, - }) -} - -func TestAccKubernetesService_externalName(t *testing.T) { - var conf api.Service - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_externalName(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.name", name), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.#", "1"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.cluster_ip", ""), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.#", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "terraform.io"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_ip", ""), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.#", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.port.#", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.selector.%", "0"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.session_affinity", "None"), - resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.type", "ExternalName"), - ), - }, - }, - }) -} - -func TestAccKubernetesService_importBasic(t *testing.T) { - resourceName := "kubernetes_service.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_basic(name), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesService_generatedName(t *testing.T) { - var conf api.Service - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_service.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesServiceExists("kubernetes_service.test", &conf), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_service.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_service.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_service.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesService_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_service.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesServiceDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesServiceConfig_generatedName(prefix), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func testAccCheckServicePorts(svc *api.Service, expected []api.ServicePort) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(svc.Spec.Ports) == 0 { - return nil - } - - ports := svc.Spec.Ports - - // Ignore NodePorts as these are assigned randomly - for k, _ := range ports { - ports[k].NodePort = 0 - } - - if !reflect.DeepEqual(ports, expected) { - return fmt.Errorf("Service ports don't match.\nExpected: %#v\nGiven: %#v", - expected, svc.Spec.Ports) - } - - return nil - } -} - -func testAccCheckKubernetesServiceDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_service" { - continue - } - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - resp, err := conn.CoreV1().Services(namespace).Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Service still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesServiceExists(n string, obj *api.Service) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - namespace, name, err := idParts(rs.Primary.ID) - if err != nil { - return err - } - - out, err := conn.CoreV1().Services(namespace).Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesServiceConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - spec { - port { - port = 8080 - target_port = 80 - } - } -}`, name) -} - -func testAccKubernetesServiceConfig_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - spec { - port { - port = 8081 - target_port = 80 - } - } -}`, name) -} - -func testAccKubernetesServiceConfig_loadBalancer(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - } - spec { - external_name = "ext-name-%s" - external_ips = ["10.0.0.3", "10.0.0.4"] - load_balancer_source_ranges = ["10.0.0.5/32", "10.0.0.6/32"] - selector { - App = "MyApp" - } - session_affinity = "ClientIP" - port { - port = 8888 - target_port = 80 - } - type = "LoadBalancer" - } -}`, name, name) -} - -func testAccKubernetesServiceConfig_loadBalancer_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - } - spec { - external_name = "ext-name-modified-%s" - external_ips = ["10.0.0.4", "10.0.0.5"] - load_balancer_source_ranges = ["10.0.0.1/32", "10.0.0.2/32"] - selector { - App = "MyModifiedApp" - NewSelector = "NewValue" - } - session_affinity = "ClientIP" - port { - port = 9999 - target_port = 81 - } - type = "LoadBalancer" - } -}`, name, name) -} - -func testAccKubernetesServiceConfig_nodePort(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - } - spec { - external_name = "ext-name-%s" - external_ips = ["10.0.0.4", "10.0.0.5"] - load_balancer_ip = "12.0.0.125" - selector { - App = "MyApp" - } - session_affinity = "ClientIP" - port { - name = "first" - port = 10222 - target_port = 22 - } - port { - name = "second" - port = 10333 - target_port = 33 - } - type = "NodePort" - } -}`, name, name) -} - -func testAccKubernetesServiceConfig_stringTargetPort(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - - labels { - app = "helloweb" - tier = "frontend" - } - } - - spec { - type = "LoadBalancer" - - selector { - app = "helloweb" - tier = "frontend" - } - - port { - port = 8080 - target_port = "http-server" - } - } - } -`, name) -} - -func testAccKubernetesServiceConfig_noTargetPort(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - } - spec { - selector { - App = "MyOtherApp" - } - port { - name = "http" - port = 80 - } - port { - name = "https" - port = 443 - } - type = "LoadBalancer" - } -} -`, name) -} - -func testAccKubernetesServiceConfig_externalName(name string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - name = "%s" - } - spec { - type = "ExternalName" - external_name = "terraform.io" - } -} -`, name) -} - -func testAccKubernetesServiceConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_service" "test" { - metadata { - generate_name = "%s" - } - spec { - port { - port = 8080 - target_port = 80 - } - } -}`, prefix) -} diff --git a/kubernetes/resource_kubernetes_storage_class.go b/kubernetes/resource_kubernetes_storage_class.go deleted file mode 100644 index 951343530d..0000000000 --- a/kubernetes/resource_kubernetes_storage_class.go +++ /dev/null @@ -1,138 +0,0 @@ -package kubernetes - -import ( - "fmt" - "log" - - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/storage/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - pkgApi "k8s.io/apimachinery/pkg/types" - kubernetes "k8s.io/client-go/kubernetes" -) - -func resourceKubernetesStorageClass() *schema.Resource { - return &schema.Resource{ - Create: resourceKubernetesStorageClassCreate, - Read: resourceKubernetesStorageClassRead, - Exists: resourceKubernetesStorageClassExists, - Update: resourceKubernetesStorageClassUpdate, - Delete: resourceKubernetesStorageClassDelete, - Importer: &schema.ResourceImporter{ - State: schema.ImportStatePassthrough, - }, - - Schema: map[string]*schema.Schema{ - "metadata": metadataSchema("storage class", true), - "parameters": { - Type: schema.TypeMap, - Description: "The parameters for the provisioner that should create volumes of this storage class", - Optional: true, - ForceNew: true, - }, - "storage_provisioner": { - Type: schema.TypeString, - Description: "Indicates the type of the provisioner", - Required: true, - ForceNew: true, - }, - }, - } -} - -func resourceKubernetesStorageClassCreate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - metadata := expandMetadata(d.Get("metadata").([]interface{})) - storageClass := api.StorageClass{ - ObjectMeta: metadata, - Provisioner: d.Get("storage_provisioner").(string), - } - - if v, ok := d.GetOk("parameters"); ok { - storageClass.Parameters = expandStringMap(v.(map[string]interface{})) - } - - log.Printf("[INFO] Creating new storage class: %#v", storageClass) - out, err := conn.StorageV1().StorageClasses().Create(&storageClass) - if err != nil { - return err - } - log.Printf("[INFO] Submitted new storage class: %#v", out) - d.SetId(out.Name) - - return resourceKubernetesStorageClassRead(d, meta) -} - -func resourceKubernetesStorageClassRead(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Reading storage class %s", name) - storageClass, err := conn.StorageV1().StorageClasses().Get(name, metav1.GetOptions{}) - if err != nil { - log.Printf("[DEBUG] Received error: %#v", err) - return err - } - log.Printf("[INFO] Received storage class: %#v", storageClass) - err = d.Set("metadata", flattenMetadata(storageClass.ObjectMeta)) - if err != nil { - return err - } - d.Set("parameters", storageClass.Parameters) - d.Set("storage_provisioner", storageClass.Provisioner) - - return nil -} - -func resourceKubernetesStorageClassUpdate(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - ops := patchMetadata("metadata.0.", "/metadata/", d) - data, err := ops.MarshalJSON() - if err != nil { - return fmt.Errorf("Failed to marshal update operations: %s", err) - } - log.Printf("[INFO] Updating storage class %q: %v", name, string(data)) - out, err := conn.StorageV1().StorageClasses().Patch(name, pkgApi.JSONPatchType, data) - if err != nil { - return fmt.Errorf("Failed to update storage class: %s", err) - } - log.Printf("[INFO] Submitted updated storage class: %#v", out) - d.SetId(buildId(out.ObjectMeta)) - - return resourceKubernetesStorageClassRead(d, meta) -} - -func resourceKubernetesStorageClassDelete(d *schema.ResourceData, meta interface{}) error { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Deleting storage class: %#v", name) - err := conn.StorageV1().StorageClasses().Delete(name, &metav1.DeleteOptions{}) - if err != nil { - return err - } - - log.Printf("[INFO] Storage class %s deleted", name) - - d.SetId("") - return nil -} - -func resourceKubernetesStorageClassExists(d *schema.ResourceData, meta interface{}) (bool, error) { - conn := meta.(*kubernetes.Clientset) - - name := d.Id() - log.Printf("[INFO] Checking storage class %s", name) - _, err := conn.StorageV1().StorageClasses().Get(name, metav1.GetOptions{}) - if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { - return false, nil - } - log.Printf("[DEBUG] Received error: %#v", err) - } - return true, err -} diff --git a/kubernetes/resource_kubernetes_storage_class_test.go b/kubernetes/resource_kubernetes_storage_class_test.go deleted file mode 100644 index d15d0e9d65..0000000000 --- a/kubernetes/resource_kubernetes_storage_class_test.go +++ /dev/null @@ -1,286 +0,0 @@ -package kubernetes - -import ( - "fmt" - "reflect" - "regexp" - "testing" - - "github.com/hashicorp/terraform/helper/acctest" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - api "k8s.io/api/storage/v1" - meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubernetes "k8s.io/client-go/kubernetes" -) - -func TestAccKubernetesStorageClass_basic(t *testing.T) { - var conf api.StorageClass - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_storage_class.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesStorageClassDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesStorageClassConfig_basic(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &conf), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.TestAnnotationTwo", "two"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "TestAnnotationTwo": "two"}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.%", "3"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.TestLabelTwo", "two"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelTwo": "two", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "storage_provisioner", "kubernetes.io/gce-pd"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.%", "1"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.type", "pd-ssd"), - testAccCheckStorageClassParameters(&conf, map[string]string{"type": "pd-ssd"}), - ), - }, - { - Config: testAccKubernetesStorageClassConfig_modified(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &conf), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.%", "2"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.TestAnnotationOne", "one"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.Different", "1234"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{"TestAnnotationOne": "one", "Different": "1234"}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.%", "2"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.TestLabelOne", "one"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.TestLabelThree", "three"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{"TestLabelOne": "one", "TestLabelThree": "three"}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "storage_provisioner", "kubernetes.io/gce-pd"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.%", "2"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.type", "pd-standard"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.zones", "us-west1-a,us-west1-b"), - testAccCheckStorageClassParameters(&conf, map[string]string{"type": "pd-standard", "zones": "us-west1-a,us-west1-b"}), - ), - }, - { - Config: testAccKubernetesStorageClassConfig_noParameters(name), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &conf), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.name", name), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.uid"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "storage_provisioner", "kubernetes.io/gce-pd"), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "parameters.%", "0"), - testAccCheckStorageClassParameters(&conf, map[string]string{}), - ), - }, - }, - }) -} - -func TestAccKubernetesStorageClass_importBasic(t *testing.T) { - resourceName := "kubernetes_storage_class.test" - name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesStorageClassDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesStorageClassConfig_basic(name), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func TestAccKubernetesStorageClass_generatedName(t *testing.T) { - var conf api.StorageClass - prefix := "tf-acc-test-gen-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - IDRefreshName: "kubernetes_storage_class.test", - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesStorageClassDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesStorageClassConfig_generatedName(prefix), - Check: resource.ComposeAggregateTestCheckFunc( - testAccCheckKubernetesStorageClassExists("kubernetes_storage_class.test", &conf), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.annotations.%", "0"), - testAccCheckMetaAnnotations(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.labels.%", "0"), - testAccCheckMetaLabels(&conf.ObjectMeta, map[string]string{}), - resource.TestCheckResourceAttr("kubernetes_storage_class.test", "metadata.0.generate_name", prefix), - resource.TestMatchResourceAttr("kubernetes_storage_class.test", "metadata.0.name", regexp.MustCompile("^"+prefix)), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.generation"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.resource_version"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.self_link"), - resource.TestCheckResourceAttrSet("kubernetes_storage_class.test", "metadata.0.uid"), - ), - }, - }, - }) -} - -func TestAccKubernetesStorageClass_importGeneratedName(t *testing.T) { - resourceName := "kubernetes_storage_class.test" - prefix := "tf-acc-test-gen-import-" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckKubernetesStorageClassDestroy, - Steps: []resource.TestStep{ - { - Config: testAccKubernetesStorageClassConfig_generatedName(prefix), - }, - - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"metadata.0.resource_version"}, - }, - }, - }) -} - -func testAccCheckStorageClassParameters(m *api.StorageClass, expected map[string]string) resource.TestCheckFunc { - return func(s *terraform.State) error { - if len(expected) == 0 && len(m.Parameters) == 0 { - return nil - } - if !reflect.DeepEqual(m.Parameters, expected) { - return fmt.Errorf("%s parameters don't match.\nExpected: %q\nGiven: %q", - m.Name, expected, m.Parameters) - } - return nil - } -} - -func testAccCheckKubernetesStorageClassDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*kubernetes.Clientset) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "kubernetes_storage_class" { - continue - } - name := rs.Primary.ID - resp, err := conn.StorageV1().StorageClasses().Get(name, meta_v1.GetOptions{}) - if err == nil { - if resp.Name == rs.Primary.ID { - return fmt.Errorf("Storage class still exists: %s", rs.Primary.ID) - } - } - } - - return nil -} - -func testAccCheckKubernetesStorageClassExists(n string, obj *api.StorageClass) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - conn := testAccProvider.Meta().(*kubernetes.Clientset) - name := rs.Primary.ID - out, err := conn.StorageV1().StorageClasses().Get(name, meta_v1.GetOptions{}) - if err != nil { - return err - } - - *obj = *out - return nil - } -} - -func testAccKubernetesStorageClassConfig_basic(name string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - TestAnnotationTwo = "two" - } - labels { - TestLabelOne = "one" - TestLabelTwo = "two" - TestLabelThree = "three" - } - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-ssd" - } -}`, name) -} - -func testAccKubernetesStorageClassConfig_modified(name string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - annotations { - TestAnnotationOne = "one" - Different = "1234" - } - labels { - TestLabelOne = "one" - TestLabelThree = "three" - } - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" - parameters { - type = "pd-standard" - zones = "us-west1-a,us-west1-b" - } -}`, name) -} - -func testAccKubernetesStorageClassConfig_noParameters(name string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" -}`, name) -} - -func testAccKubernetesStorageClassConfig_generatedName(prefix string) string { - return fmt.Sprintf(` -resource "kubernetes_storage_class" "test" { - metadata { - generate_name = "%s" - } - storage_provisioner = "kubernetes.io/gce-pd" -}`, prefix) -} diff --git a/kubernetes/resource_kubernetes_yaml.go b/kubernetes/resource_kubernetes_yaml.go new file mode 100644 index 0000000000..bbf747e5f1 --- /dev/null +++ b/kubernetes/resource_kubernetes_yaml.go @@ -0,0 +1,541 @@ +package kubernetes + +import ( + "crypto/md5" + "encoding/hex" + "fmt" + "log" + "reflect" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + k8meta "k8s.io/apimachinery/pkg/api/meta" + meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + meta_v1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1" + "k8s.io/apimachinery/pkg/conversion" + "k8s.io/apimachinery/pkg/runtime" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" +) + +func resourceKubernetesYAML() *schema.Resource { + return &schema.Resource{ + Create: resourceKubernetesYAMLCreate, + Read: resourceKubernetesYAMLRead, + Exists: resourceKubernetesYAMLExists, + Delete: resourceKubernetesYAMLDelete, + Update: resourceKubernetesYAMLUpdate, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + CustomizeDiff: func(d *schema.ResourceDiff, meta interface{}) error { + // Enable force new on yaml_body field. + // This can't be done in the schema as it will fail internal validation + // as all fields would be 'ForceNew' so no 'Update' func is needed. + // but as we manually trigger an update in this compare function + // we need the update function specified. + d.ForceNew("yaml_body") + + // Get the UID of the K8s resource as it was when the `resourceKubernetesYAMLCreate` func completed. + createdAtUID := d.Get("uid").(string) + // Get the UID of the K8s resource as it currently is in the cluster. + UID, exists := d.Get("live_uid").(string) + if !exists { + return nil + } + + // Get the ResourceVersion of the K8s resource as it was when the `resourceKubernetesYAMLCreate` func completed. + createdAtResourceVersion := d.Get("resource_version").(string) + // Get it as it currently is in the cluster + resourceVersion, exists := d.Get("live_resource_version").(string) + if !exists { + return nil + } + + // If either UID or ResourceVersion differ between the current state and the cluster + // trigger an update on the resource to get back in sync + if UID != createdAtUID { + log.Printf("[CUSTOMDIFF] DETECTED %s vs %s", UID, createdAtUID) + d.SetNewComputed("uid") + return nil + } + + if resourceVersion != createdAtResourceVersion { + log.Printf("[CUSTOMDIFF] DETECTED RESOURCE VERSION %s vs %s", resourceVersion, createdAtResourceVersion) + // Check that the fields specified in our YAML for diff against cluster representation + stateYaml := d.Get("yaml_incluster").(string) + liveStateYaml := d.Get("live_yaml_incluster").(string) + if stateYaml != liveStateYaml { + log.Printf("[CUSTOMDIFF] DETECTED YAML STATE %s vs %s", stateYaml, liveStateYaml) + d.SetNewComputed("yaml_incluster") + + } + return nil + } + + return nil + }, + Schema: map[string]*schema.Schema{ + "uid": { + Type: schema.TypeString, + Computed: true, + }, + "resource_version": { + Type: schema.TypeString, + Computed: true, + }, + "live_uid": { + Type: schema.TypeString, + Computed: true, + }, + "live_resource_version": { + Type: schema.TypeString, + Computed: true, + }, + "yaml_incluster": { + Type: schema.TypeString, + Computed: true, + }, + "live_yaml_incluster": { + Type: schema.TypeString, + Computed: true, + }, + "yaml_body": { + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func resourceKubernetesYAMLCreate(d *schema.ResourceData, meta interface{}) error { + yaml := d.Get("yaml_body").(string) + + // Create a client to talk to the resource API based on the APIVersion and Kind + // defined in the YAML + client, absPath, rawObj, err := getRestClientFromYaml(yaml, meta.(KubeProvider)) + if err != nil { + return fmt.Errorf("failed to create kubernetes rest client for resource: %+v", err) + } + // Create the resource in Kubernetes + response := client.Post().AbsPath(absPath["POST"]).Body(rawObj).Do() + if response.Error() != nil { + return fmt.Errorf("failed to create resource in kubernetes: %+v", response.Error()) + } + + // Another error occured + result, err := response.Get() + if err != nil { + return err + } + metaObj, err := runtimeObjToMetaObj(result) + if err != nil { + return err + } + + d.SetId(metaObj.GetSelfLink()) + // Capture the UID and Resource_version at time of creation + // this allows us to diff these against the actual values + // read in by the 'resourceKubernetesYAMLRead' + d.Set("uid", metaObj.UID) + d.Set("resource_version", metaObj.ResourceVersion) + builder := strings.Builder{} + err = compareObjs(rawObj, result, &builder) + if err != nil { + return err + } + d.Set("yaml_incluster", getMD5Hash(builder.String())) + + return resourceKubernetesYAMLRead(d, meta) +} + +func resourceKubernetesYAMLRead(d *schema.ResourceData, meta interface{}) error { + yaml := d.Get("yaml_body").(string) + + // Create a client to talk to the resource API based on the APIVersion and Kind + // defined in the YAML + client, absPaths, rawObj, err := getRestClientFromYaml(yaml, meta.(KubeProvider)) + if err != nil { + return fmt.Errorf("failed to create kubernetes rest client for resource: %+v", err) + } + + // Get the resource from Kubernetes + metaObjLive, rawObjLive, exists, err := getResourceFromK8s(client, absPaths) + if err != nil { + return fmt.Errorf("failed to get resource '%s' from kubernetes: %+v", metaObjLive.SelfLink, err) + } + if !exists { + return fmt.Errorf("resource '%s' reading didn't exist", metaObjLive.SelfLink) + } + + if metaObjLive.UID == "" { + return fmt.Errorf("Failed to parse item and get UUID: %+v", metaObjLive) + } + + // Capture the UID and Resource_version from the cluster at the current time + d.Set("live_uid", metaObjLive.UID) + d.Set("live_resource_version", metaObjLive.ResourceVersion) + + builder := strings.Builder{} + err = compareObjs(rawObj, rawObjLive, &builder) + if err != nil { + return err + } + d.Set("live_yaml_incluster", getMD5Hash(builder.String())) + + return nil +} + +func resourceKubernetesYAMLDelete(d *schema.ResourceData, meta interface{}) error { + yaml := d.Get("yaml_body").(string) + + client, absPaths, _, err := getRestClientFromYaml(yaml, meta.(KubeProvider)) + if err != nil { + return fmt.Errorf("failed to create kubernetes rest client for resource: %+v", err) + } + + metaObj := &meta_v1beta1.PartialObjectMetadata{} + err = client.Delete().AbsPath(absPaths["DELETE"]).Do().Into(metaObj) + if err != nil { + return fmt.Errorf("failed to delete kubernetes resource '%s': %+v", metaObj.SelfLink, err) + } + + // Success remove it from state + d.SetId("") + + return nil +} + +func resourceKubernetesYAMLUpdate(d *schema.ResourceData, meta interface{}) error { + err := resourceKubernetesYAMLDelete(d, meta) + if err != nil { + return err + } + return resourceKubernetesYAMLCreate(d, meta) +} + +func resourceKubernetesYAMLExists(d *schema.ResourceData, meta interface{}) (bool, error) { + yaml := d.Get("yaml_body").(string) + + client, absPaths, _, err := getRestClientFromYaml(yaml, meta.(KubeProvider)) + if err != nil { + return false, fmt.Errorf("failed to create kubernetes rest client for resource: %+v", err) + } + + metaObj, _, exists, err := getResourceFromK8s(client, absPaths) + if err != nil { + return false, fmt.Errorf("failed to get resource '%s' from kubernetes: %+v", metaObj.SelfLink, err) + } + if exists { + return true, nil + } + return false, nil +} + +func getResourceFromK8s(client rest.Interface, absPaths map[string]string) (*meta_v1beta1.PartialObjectMetadata, runtime.Object, bool, error) { + result := client.Get().AbsPath(absPaths["GET"]).Do() + + var statusCode int + result.StatusCode(&statusCode) + // Resource doesn't exist + if statusCode != 200 { + return nil, nil, false, nil + } + + // Another error occured + response, err := result.Get() + if err != nil { + return nil, nil, false, err + } + + // Get the metadata we need + metaObj, err := runtimeObjToMetaObj(response) + if err != nil { + return nil, nil, true, err + } + + return metaObj, response, true, err +} + +func getRestClientFromYaml(yaml string, provider KubeProvider) (*rest.RESTClient, map[string]string, runtime.Object, error) { + absPaths := map[string]string{} + metaObj, rawObj, err := getResourceMetaObjFromYaml(yaml) + if err != nil { + return nil, absPaths, nil, err + } + + // Use the k8s Discovery service to find all valid APIs for this cluster + clientSet, config := provider() + discovery := clientSet.Discovery() + resources, err := discovery.ServerResources() + if err != nil { + return nil, absPaths, nil, err + } + + // Validate that the APIVersion provided in the YAML is valid for this cluster + apiResource, exists := checkAPIResourceIsPresent(resources, metaObj) + if !exists { + return nil, absPaths, nil, fmt.Errorf("resource provided in yaml isn't valid for cluster, check the APIVersion and Kind fields are valid") + } + + // Create rest config for the correct API based + // on the YAML input + gv := metaObj.TypeMeta.GroupVersionKind().GroupVersion() + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} + config.GroupVersion = &gv + + config.APIPath = "apis" + // Handle special case for coreapis + if gv.String() == "v1" { + config.APIPath = "api" + } + + restClient, err := rest.RESTClientFor(&config) + if err != nil { + return nil, absPaths, nil, err + } + + log.Printf("[REST CREATE] GroupVersion: %#v", gv.String()) + + // To simplify usage of the client in each of the users of this func + // we build up the correct AbsPaths to use with the rest client + // this centralises logic around namespaced vs non-namespaced resources + // leaving CRUD operations to simply select the right AbsPath to use + // Note: This uses the APIResource information from the server to correctly + // construct the URL for any supported resource on the server and isn't limited + // to those present in the typed client. + if apiResource.Namespaced { + absPaths["GET"] = fmt.Sprintf("/%s/%s/namespaces/%s/%s/%s", config.APIPath, gv.String(), metaObj.Namespace, apiResource.Name, metaObj.Name) + absPaths["DELETE"] = fmt.Sprintf("/%s/%s/namespaces/%s/%s/%s", config.APIPath, gv.String(), metaObj.Namespace, apiResource.Name, metaObj.Name) + absPaths["POST"] = fmt.Sprintf("/%s/%s/namespaces/%s/%s/", config.APIPath, gv.String(), metaObj.Namespace, apiResource.Name) + } else { + absPaths["GET"] = fmt.Sprintf("/%s/%s/%s/%s", config.APIPath, gv.String(), apiResource.Name, metaObj.Name) + absPaths["DELETE"] = fmt.Sprintf("/%s/%s/%s/%s", config.APIPath, gv.String(), apiResource.Name, metaObj.Name) + absPaths["POST"] = fmt.Sprintf("/%s/%s/%s/", config.APIPath, gv.String(), apiResource.Name) + } + + return restClient, absPaths, rawObj, nil +} + +// getResourceMetaObjFromYaml Uses the UniversalDeserializer to deserialize +// the yaml provided into a k8s runtime.Object +func getResourceMetaObjFromYaml(yaml string) (*meta_v1beta1.PartialObjectMetadata, runtime.Object, error) { + decoder := scheme.Codecs.UniversalDeserializer() + obj, _, err := decoder.Decode([]byte(yaml), nil, nil) + if err != nil { + log.Printf("[INFO] Error parsing type: %#v", err) + return nil, nil, err + } + metaObj, err := runtimeObjToMetaObj(obj) + if err != nil { + return nil, nil, err + } + return metaObj, obj, nil + +} + +// checkAPIResourceIsPresent Loops through a list of available APIResources and +// checks there is a resource for the APIVersion and Kind defined in the 'resource' +// if found it returns true and the APIResource which matched +func checkAPIResourceIsPresent(available []*meta_v1.APIResourceList, resource *meta_v1beta1.PartialObjectMetadata) (*meta_v1.APIResource, bool) { + for _, rList := range available { + if rList == nil { + continue + } + group := rList.GroupVersion + for _, r := range rList.APIResources { + if group == resource.TypeMeta.APIVersion && r.Kind == resource.Kind { + return &r, true + } + } + } + return nil, false +} + +// runtimeObjToMetaObj Gets a subset of the full object information +// just enough to construct the API Calls needed and detect any changes +// made to the object in the cluster (UID & ResourceVersion) +func runtimeObjToMetaObj(obj runtime.Object) (*meta_v1beta1.PartialObjectMetadata, error) { + metaObj := k8meta.AsPartialObjectMetadata(obj.(meta_v1.Object)) + typeMeta, err := k8meta.TypeAccessor(obj) + if err != nil { + return nil, err + } + metaObj.TypeMeta = meta_v1.TypeMeta{ + APIVersion: typeMeta.GetAPIVersion(), + Kind: typeMeta.GetKind(), + } + if metaObj.Namespace == "" { + metaObj.Namespace = "default" + } + return metaObj, nil +} + +func compareObjs(original, returned interface{}, builder *strings.Builder) error { + // Check originalObj is valid + originalObj, err := conversion.EnforcePtr(original) + if err != nil { + return err + } + + // Check returnedObj is valid + returnedObj, err := conversion.EnforcePtr(returned) + if err != nil { + return err + } + return compareObjsInternal(originalObj, returnedObj, builder) +} + +var skipFields = map[string]bool{ + "Status": true, + "Finalizers": true, + "Initializers": true, + "OwnerReferences": true, + "CreationTimestamp": true, + "Generation": true, + "ResourceVersion": true, + "UID": true, +} + +func compareObjsInternal(originalObj, returnedObj reflect.Value, builder *strings.Builder) error { + originalObType := originalObj.Type() + if originalObType.Kind() != reflect.Struct { + return fmt.Errorf("expected struct, but got %v: %v", originalObj.Kind(), originalObj) + } + + returnedObjType := returnedObj.Type() + if returnedObjType.Kind() != reflect.Struct { + return fmt.Errorf("expected struct, but got %v: %v", returnedObj.Kind(), returnedObj) + } + + // Loop through all fields on the original Obj + // for each field on the original get it's value on the returned obj + // and use this to build a hash + for iO := 0; iO < originalObType.NumField(); iO++ { + originalField := originalObType.Field(iO) + + for iR := 0; iR < returnedObjType.NumField(); iR++ { + returnedField := returnedObjType.Field(iR) + + // Check we're comparing the right field + if returnedField.Name != originalField.Name { + log.Printf("[COMPARE] Skipping: %#v %#v", returnedField, originalField) + continue + } + + // Skip any fields we want to ignore + if _, exists := skipFields[returnedField.Name]; exists { + log.Printf("[COMPARE] Skipping as in SkipFields: %#v %#v", returnedField, originalField) + continue + } + + // Get the value of the field and pull value + // out if the field is a ptr + originalValue := originalObj.Field(iO) + if originalValue.Kind() == reflect.Ptr { + if originalValue.IsNil() { + log.Printf("[COMPARE] Skipping as is nil ptr: %#v %#v", returnedField, originalField) + continue + } + originalValue = originalValue.Elem() + } + returnedValue := returnedObj.Field(iO) + if returnedValue.Kind() == reflect.Ptr { + if returnedValue.IsNil() { + log.Printf("[COMPARE] Skipping as is nil ptr: %#v %#v", returnedField, originalField) + continue + } + returnedValue = returnedValue.Elem() + } + + log.Printf("[COMPARE] Found matching field: %#v, %#v", returnedField.Name, returnedValue.Type().Kind().String()) + + // Recurse into the struct to compare it's fields + if returnedValue.Type().Kind() == reflect.Struct { + log.Printf("[COMPARE] Found struct recurrsing: %#v", returnedField) + + err := compareObjsInternal(originalValue, returnedValue, builder) + if err != nil { + return err + } + continue + } + + // Skip unneeded fields + k := returnedValue.Kind() + switch k { + case reflect.String: + if returnedValue.String() == "" { + log.Printf("[COMPARE] Skipping empty string value: %#v %#v", returnedField, originalField) + continue + } + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice: + + // We can check if these are nil + if returnedValue.IsNil() { + log.Printf("[COMPARE] Skipping nil value: %#v %#v", returnedField, originalField) + continue + } + } + + // We can do a more detailed comparison on map fields + if k == reflect.Map { + log.Printf("[COMPARE] Comparing map: %#v %#v", returnedField, originalField) + + returnedKeys := returnedValue.MapKeys() + originalKeys := originalValue.MapKeys() + + for _, oKey := range originalKeys { + for _, rKey := range returnedKeys { + if oKey.String() == rKey.String() { + rValue := returnedValue.MapIndex(rKey) + + log.Printf("[COMPARE] Found matching map value. Writing to string builder: %s->%#v", returnedField.Name, returnedValue.Interface()) + builder.WriteString(fmt.Sprintf("fieldName:%s,keyName:%s,fieldValue:%v", returnedField.Name, oKey.String(), rValue.Interface())) + } + } + } + + return nil + } + + // We can do a more detailed comparison for arrays too + if k == reflect.Slice { + log.Printf("[COMPARE] Comparing slice: %#v %#v", returnedField, originalField) + + oSliceLen := originalValue.Len() + rSliceLen := returnedValue.Len() + if rSliceLen < oSliceLen { + //Todo: what do we do here? + panic("wrong size") + } + + for i := 0; i < oSliceLen; i++ { + log.Printf("[COMPARE] Recurse for Array/slice item: %#v %#v", returnedField, originalField) + + err := compareObjsInternal(originalValue.Index(i), returnedValue.Index(i), builder) + if err != nil { + return err + } + } + + return nil + } + + if returnedValue.CanInterface() { + log.Printf("[COMPARE] Found value writing to string builder: %s->%#v (%#v)", returnedField.Name, returnedValue.Interface(), returnedValue.Kind().String()) + builder.WriteString(fmt.Sprintf("fieldName:%s,fieldValue:%v", returnedField.Name, returnedValue.Interface())) + } else { + log.Printf("[COMPARE] Found unsettable field :(: %#v", returnedField.Name) + } + } + } + + return nil +} + +func getMD5Hash(text string) string { + hash := md5.Sum([]byte(text)) + return hex.EncodeToString(hash[:]) +} diff --git a/kubernetes/schema_container.go b/kubernetes/schema_container.go deleted file mode 100644 index c6d6768204..0000000000 --- a/kubernetes/schema_container.go +++ /dev/null @@ -1,648 +0,0 @@ -package kubernetes - -import "github.com/hashicorp/terraform/helper/schema" - -func handlerFields() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "exec": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "exec specifies the action to take.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "command": { - Type: schema.TypeList, - Description: `Command is the command line to execute inside the container, the working directory for the command is root ('/') in the container's filesystem. The command is simply exec'd, it is not run inside a shell, so traditional shell instructions. To use a shell, you need to explicitly call out to that shell. Exit status of 0 is treated as live/healthy and non-zero is unhealthy.`, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - }, - }, - }, - }, - "http_get": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Specifies the http request to perform.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "host": { - Type: schema.TypeString, - Optional: true, - Description: `Host name to connect to, defaults to the pod IP. You probably want to set "Host" in httpHeaders instead.`, - }, - "path": { - Type: schema.TypeString, - Optional: true, - Description: `Path to access on the HTTP server.`, - }, - "scheme": { - Type: schema.TypeString, - Optional: true, - Default: "HTTP", - Description: `Scheme to use for connecting to the host.`, - }, - "port": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validatePortNumOrName, - Description: `Name or number of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.`, - }, - "http_header": { - Type: schema.TypeList, - Optional: true, - Description: `Scheme to use for connecting to the host.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Optional: true, - Description: "The header field name", - }, - "value": { - Type: schema.TypeString, - Optional: true, - Description: "The header field value", - }, - }, - }, - }, - }, - }, - }, - "tcp_socket": { - Type: schema.TypeList, - Optional: true, - Description: "TCPSocket specifies an action involving a TCP port. TCP hooks not yet supported", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "port": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validatePortNumOrName, - Description: "Number or name of the port to access on the container. Number must be in the range 1 to 65535. Name must be an IANA_SVC_NAME.", - }, - }, - }, - }, - } -} - -func resourcesField() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "limits": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Description: "Describes the maximum amount of compute resources allowed. More info: http://kubernetes.io/docs/user-guide/compute-resources/", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cpu": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validateResourceQuantity, - DiffSuppressFunc: suppressEquivalentResourceQuantity, - }, - "memory": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validateResourceQuantity, - DiffSuppressFunc: suppressEquivalentResourceQuantity, - }, - }, - }, - }, - "requests": { - Type: schema.TypeList, - Optional: true, - Computed: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "cpu": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validateResourceQuantity, - DiffSuppressFunc: suppressEquivalentResourceQuantity, - }, - "memory": { - Type: schema.TypeString, - Optional: true, - Computed: true, - ValidateFunc: validateResourceQuantity, - DiffSuppressFunc: suppressEquivalentResourceQuantity, - }, - }, - }, - }, - } -} - -func seLinuxOptionsField() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "level": { - Type: schema.TypeString, - Optional: true, - Description: "Level is SELinux level label that applies to the container.", - }, - "role": { - Type: schema.TypeString, - Optional: true, - Description: "Role is a SELinux role label that applies to the container.", - }, - "type": { - Type: schema.TypeString, - Optional: true, - Description: "Type is a SELinux type label that applies to the container.", - }, - "user": { - Type: schema.TypeString, - Optional: true, - Description: "User is a SELinux user label that applies to the container.", - }, - } -} - -func volumeMountFields() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "mount_path": { - Type: schema.TypeString, - Required: true, - Description: "Path within the container at which the volume should be mounted. Must not contain ':'.", - }, - "name": { - Type: schema.TypeString, - Required: true, - Description: "This must match the Name of a Volume.", - }, - "read_only": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false.", - }, - "sub_path": { - Type: schema.TypeString, - Optional: true, - Description: `Path within the volume from which the container's volume should be mounted. Defaults to "" (volume's root).`, - }, - } -} - -func containerFields(isUpdatable, isInitContainer bool) map[string]*schema.Schema { - s := map[string]*schema.Schema{ - "args": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Arguments to the entrypoint. The docker image's CMD is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers#containers-and-commands", - }, - "command": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Entrypoint array. Not executed within a shell. The docker image's ENTRYPOINT is used if this is not provided. Variable references $(VAR_NAME) are expanded using the container's environment. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers#containers-and-commands", - }, - "env": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Description: "List of environment variables to set in the container. Cannot be updated.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - Description: "Name of the environment variable. Must be a C_IDENTIFIER", - }, - "value": { - Type: schema.TypeString, - ForceNew: true, - Optional: true, - Description: `Variable references $(VAR_NAME) are expanded using the previous defined environment variables in the container and any service environment variables. If a variable cannot be resolved, the reference in the input string will be unchanged. The $(VAR_NAME) syntax can be escaped with a double $$, ie: $$(VAR_NAME). Escaped references will never be expanded, regardless of whether the variable exists or not. Defaults to "".`, - }, - "value_from": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Source for the environment variable's value", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "config_map_key_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Selects a key of a ConfigMap.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Optional: true, - Description: "The key to select.", - }, - "name": { - Type: schema.TypeString, - Optional: true, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - }, - }, - }, - }, - "field_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP..", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "api_version": { - Type: schema.TypeString, - Optional: true, - Default: "v1", - Description: `Version of the schema the FieldPath is written in terms of, defaults to "v1".`, - }, - "field_path": { - Type: schema.TypeString, - Optional: true, - Description: "Path of the field to select in the specified API version", - }, - }, - }, - }, - "resource_field_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP..", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "container_name": { - Type: schema.TypeString, - Optional: true, - }, - "resource": { - Type: schema.TypeString, - Required: true, - Description: "Resource to select", - }, - }, - }, - }, - "secret_key_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Selects a field of the pod: supports metadata.name, metadata.namespace, metadata.labels, metadata.annotations, spec.nodeName, spec.serviceAccountName, status.podIP..", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Optional: true, - Description: "The key of the secret to select from. Must be a valid secret key.", - }, - "name": { - Type: schema.TypeString, - Optional: true, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - "env_from": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Description: "List of sources to populate environment variables in the container. The keys defined within a source must be a C_IDENTIFIER. All invalid keys will be reported as an event when the container is starting. When a key exists in multiple sources, the value associated with the last source will take precedence. Values defined by an Env with a duplicate key will take precedence. Cannot be updated.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "config_map_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "The ConfigMap to select from", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - }, - "optional": { - Type: schema.TypeBool, - Optional: true, - Description: "Specify whether the ConfigMap must be defined", - }, - }, - }, - }, - "prefix": { - Type: schema.TypeString, - Optional: true, - Description: "An optional identifer to prepend to each key in the ConfigMap. Must be a C_IDENTIFIER.", - }, - "secret_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "The Secret to select from", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Required: true, - Description: "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", - }, - "optional": { - Type: schema.TypeBool, - Optional: true, - Description: "Specify whether the Secret must be defined", - }, - }, - }, - }, - }, - }, - }, - "image": { - Type: schema.TypeString, - Optional: true, - Description: "Docker image name. More info: http://kubernetes.io/docs/user-guide/images", - }, - "image_pull_policy": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "Image pull policy. One of Always, Never, IfNotPresent. Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/images#updating-images", - }, - "lifecycle": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ForceNew: true, - Description: "Actions that the management system should take in response to container lifecycle events", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "post_start": { - Type: schema.TypeList, - Description: `post_start is called immediately after a container is created. If the handler fails, the container is terminated and restarted according to its restart policy. Other management of the container blocks until the hook completes. More info: http://kubernetes.io/docs/user-guide/container-environment#hook-details`, - Optional: true, - Elem: &schema.Resource{ - Schema: handlerFields(), - }, - }, - "pre_stop": { - Type: schema.TypeList, - Description: `pre_stop is called immediately before a container is terminated. The container is terminated after the handler completes. The reason for termination is passed to the handler. Regardless of the outcome of the handler, the container is eventually terminated. Other management of the container blocks until the hook completes. More info: http://kubernetes.io/docs/user-guide/container-environment#hook-details`, - Optional: true, - Elem: &schema.Resource{ - Schema: handlerFields(), - }, - }, - }, - }, - }, - "liveness_probe": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ForceNew: true, - Description: "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/pod-states#container-probes", - Elem: probeSchema(), - }, - "name": { - Type: schema.TypeString, - Required: true, - Description: "Name of the container specified as a DNS_LABEL. Each container in a pod must have a unique name (DNS_LABEL). Cannot be updated.", - }, - "port": { - Type: schema.TypeList, - Optional: true, - Description: `List of ports to expose from the container. Exposing a port here gives the system additional information about the network connections a container uses, but is primarily informational. Not specifying a port here DOES NOT prevent that port from being exposed. Any port which is listening on the default "0.0.0.0" address inside a container will be accessible from the network. Cannot be updated.`, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "container_port": { - Type: schema.TypeInt, - Required: true, - ValidateFunc: validatePortNumOrName, - Description: "Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536.", - }, - "host_ip": { - Type: schema.TypeString, - Optional: true, - Description: "What host IP to bind the external port to.", - }, - "host_port": { - Type: schema.TypeInt, - Optional: true, - Description: "Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this.", - }, - "name": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validatePortNumOrName, - Description: "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services", - }, - "protocol": { - Type: schema.TypeString, - Optional: true, - Description: `Protocol for port. Must be UDP or TCP. Defaults to "TCP".`, - Default: "TCP", - }, - }, - }, - }, - "readiness_probe": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ForceNew: true, - Description: "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/pod-states#container-probes", - Elem: probeSchema(), - }, - "resources": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Computed: true, - Description: "Compute Resources required by this container. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#resources", - Elem: &schema.Resource{ - Schema: resourcesField(), - }, - }, - - "security_context": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - ForceNew: true, - Description: "Security options the pod should run with. More info: http://releases.k8s.io/HEAD/docs/design/security_context.md", - Elem: securityContextSchema(), - }, - "stdin": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Whether this container should allocate a buffer for stdin in the container runtime. If this is not set, reads from stdin in the container will always result in EOF. ", - }, - "stdin_once": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Whether the container runtime should close the stdin channel after it has been opened by a single attach. When stdin is true the stdin stream will remain open across multiple attach sessions. If stdinOnce is set to true, stdin is opened on container start, is empty until the first client attaches to stdin, and then remains open and accepts data until the client disconnects, at which time stdin is closed and remains closed until the container is restarted. If this flag is false, a container processes that reads from stdin will never receive an EOF.", - }, - "termination_message_path": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Default: "/dev/termination-log", - Description: "Optional: Path at which the file to which the container's termination message will be written is mounted into the container's filesystem. Message written is intended to be brief final status, such as an assertion failure message. Defaults to /dev/termination-log. Cannot be updated.", - }, - "tty": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Whether this container should allocate a TTY for itself", - }, - "volume_mount": { - Type: schema.TypeList, - Optional: true, - Description: "Pod volumes to mount into the container's filesystem. Cannot be updated.", - Elem: &schema.Resource{ - Schema: volumeMountFields(), - }, - }, - "working_dir": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Description: "Container's working directory. If not specified, the container runtime's default will be used, which might be configured in the container image. Cannot be updated.", - }, - } - - if !isUpdatable { - for k, _ := range s { - if k == "image" && !isInitContainer { - // this field is updatable for non-init containers - continue - } - s[k].ForceNew = true - } - } - - return s -} - -func probeSchema() *schema.Resource { - h := handlerFields() - h["failure_threshold"] = &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Description: "Minimum consecutive failures for the probe to be considered failed after having succeeded.", - Default: 3, - ValidateFunc: validatePositiveInteger, - } - h["initial_delay_seconds"] = &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Description: "Number of seconds after the container has started before liveness probes are initiated. More info: http://kubernetes.io/docs/user-guide/pod-states#container-probes", - } - h["period_seconds"] = &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Default: 10, - ValidateFunc: validatePositiveInteger, - Description: "How often (in seconds) to perform the probe", - } - h["success_threshold"] = &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Default: 1, - ValidateFunc: validatePositiveInteger, - Description: "Minimum consecutive successes for the probe to be considered successful after having failed.", - } - - h["timeout_seconds"] = &schema.Schema{ - Type: schema.TypeInt, - Optional: true, - Default: 1, - ValidateFunc: validatePositiveInteger, - Description: "Number of seconds after which the probe times out. More info: http://kubernetes.io/docs/user-guide/pod-states#container-probes", - } - return &schema.Resource{ - Schema: h, - } - -} - -func securityContextSchema() *schema.Resource { - m := map[string]*schema.Schema{ - "privileged": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: `Run container in privileged mode. Processes in privileged containers are essentially equivalent to root on the host.`, - }, - "read_only_root_filesystem": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Whether this container has a read-only root filesystem.", - }, - "run_as_non_root": { - Type: schema.TypeBool, - Description: "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does.", - Optional: true, - }, - "run_as_user": { - Type: schema.TypeInt, - Description: "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified", - Optional: true, - }, - "se_linux_options": { - Type: schema.TypeList, - Description: "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: seLinuxOptionsField(), - }, - }, - "capabilities": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "The capabilities to add/drop when running containers. Defaults to the default set of capabilities granted by the container runtime.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "add": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Added capabilities", - }, - "drop": { - Type: schema.TypeList, - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Description: "Removed capabilities", - }, - }, - }, - }, - } - - return &schema.Resource{ - Schema: m, - } -} diff --git a/kubernetes/schema_label_selector.go b/kubernetes/schema_label_selector.go deleted file mode 100644 index ceeee79d75..0000000000 --- a/kubernetes/schema_label_selector.go +++ /dev/null @@ -1,46 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" -) - -func labelSelectorFields() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "match_expressions": { - Type: schema.TypeList, - Description: "A list of label selector requirements. The requirements are ANDed.", - Optional: true, - ForceNew: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Description: "The label key that the selector applies to.", - Optional: true, - ForceNew: true, - }, - "operator": { - Type: schema.TypeString, - Description: "A key's relationship to a set of values. Valid operators ard `In`, `NotIn`, `Exists` and `DoesNotExist`.", - Optional: true, - ForceNew: true, - }, - "values": { - Type: schema.TypeSet, - Description: "An array of string values. If the operator is `In` or `NotIn`, the values array must be non-empty. If the operator is `Exists` or `DoesNotExist`, the values array must be empty. This array is replaced during a strategic merge patch.", - Optional: true, - ForceNew: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - }, - }, - }, - "match_labels": { - Type: schema.TypeMap, - Description: "A map of {key,value} pairs. A single {key,value} in the matchLabels map is equivalent to an element of `match_expressions`, whose key field is \"key\", the operator is \"In\", and the values array contains only \"value\". The requirements are ANDed.", - Optional: true, - ForceNew: true, - }, - } -} diff --git a/kubernetes/schema_metadata.go b/kubernetes/schema_metadata.go deleted file mode 100644 index 40a75d996c..0000000000 --- a/kubernetes/schema_metadata.go +++ /dev/null @@ -1,112 +0,0 @@ -package kubernetes - -import ( - "fmt" - - "github.com/hashicorp/terraform/helper/schema" -) - -func metadataFields(objectName string) map[string]*schema.Schema { - return map[string]*schema.Schema{ - "annotations": { - Type: schema.TypeMap, - Description: fmt.Sprintf("An unstructured key value map stored with the %s that may be used to store arbitrary metadata. More info: http://kubernetes.io/docs/user-guide/annotations", objectName), - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - ValidateFunc: validateAnnotations, - }, - "generation": { - Type: schema.TypeInt, - Description: "A sequence number representing a specific generation of the desired state.", - Computed: true, - }, - "labels": { - Type: schema.TypeMap, - Description: fmt.Sprintf("Map of string keys and values that can be used to organize and categorize (scope and select) the %s. May match selectors of replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels", objectName), - Optional: true, - Elem: &schema.Schema{Type: schema.TypeString}, - ValidateFunc: validateLabels, - }, - "name": { - Type: schema.TypeString, - Description: fmt.Sprintf("Name of the %s, must be unique. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names", objectName), - Optional: true, - ForceNew: true, - Computed: true, - ValidateFunc: validateName, - }, - "resource_version": { - Type: schema.TypeString, - Description: fmt.Sprintf("An opaque value that represents the internal version of this %s that can be used by clients to determine when %s has changed. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#concurrency-control-and-consistency", objectName, objectName), - Computed: true, - }, - "self_link": { - Type: schema.TypeString, - Description: fmt.Sprintf("A URL representing this %s.", objectName), - Computed: true, - }, - "uid": { - Type: schema.TypeString, - Description: fmt.Sprintf("The unique in time and space value for this %s. More info: http://kubernetes.io/docs/user-guide/identifiers#uids", objectName), - Computed: true, - }, - } -} - -func metadataSchema(objectName string, generatableName bool) *schema.Schema { - fields := metadataFields(objectName) - - if generatableName { - fields["generate_name"] = &schema.Schema{ - Type: schema.TypeString, - Description: "Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#idempotency", - Optional: true, - ForceNew: true, - ValidateFunc: validateGenerateName, - ConflictsWith: []string{"metadata.name"}, - } - fields["name"].ConflictsWith = []string{"metadata.generate_name"} - } - - return &schema.Schema{ - Type: schema.TypeList, - Description: fmt.Sprintf("Standard %s's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata", objectName), - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: fields, - }, - } -} - -func namespacedMetadataSchema(objectName string, generatableName bool) *schema.Schema { - fields := metadataFields(objectName) - fields["namespace"] = &schema.Schema{ - Type: schema.TypeString, - Description: fmt.Sprintf("Namespace defines the space within which name of the %s must be unique.", objectName), - Optional: true, - ForceNew: true, - Default: "default", - } - if generatableName { - fields["generate_name"] = &schema.Schema{ - Type: schema.TypeString, - Description: "Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. Read more: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#idempotency", - Optional: true, - ForceNew: true, - ValidateFunc: validateGenerateName, - ConflictsWith: []string{"metadata.name"}, - } - fields["name"].ConflictsWith = []string{"metadata.generate_name"} - } - - return &schema.Schema{ - Type: schema.TypeList, - Description: fmt.Sprintf("Standard %s's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#metadata", objectName), - Required: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: fields, - }, - } -} diff --git a/kubernetes/schema_pod_spec.go b/kubernetes/schema_pod_spec.go deleted file mode 100644 index 4f9a950670..0000000000 --- a/kubernetes/schema_pod_spec.go +++ /dev/null @@ -1,438 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" -) - -func podSpecFields(isUpdatable bool) map[string]*schema.Schema { - s := map[string]*schema.Schema{ - "active_deadline_seconds": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validatePositiveInteger, - Description: "Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.", - }, - "container": { - Type: schema.TypeList, - Optional: true, - Description: "List of containers belonging to the pod. Containers cannot currently be added or removed. There must be at least one container in a Pod. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/containers", - Elem: &schema.Resource{ - Schema: containerFields(isUpdatable, false), - }, - }, - "init_container": { - Type: schema.TypeList, - Optional: true, - ForceNew: true, - Description: "List of init containers belonging to the pod. Init containers always run to completion and each must complete succesfully before the next is started. More info: https://kubernetes.io/docs/concepts/workloads/pods/init-containers/", - Elem: &schema.Resource{ - Schema: containerFields(isUpdatable, true), - }, - }, - "dns_policy": { - Type: schema.TypeString, - Optional: true, - Default: "ClusterFirst", - Description: "Set DNS policy for containers within the pod. One of 'ClusterFirst' or 'Default'. Defaults to 'ClusterFirst'.", - }, - "host_ipc": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Use the host's ipc namespace. Optional: Default to false.", - }, - "host_network": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Host networking requested for this pod. Use the host's network namespace. If this option is set, the ports that will be used must be specified.", - }, - - "host_pid": { - Type: schema.TypeBool, - Optional: true, - Default: false, - Description: "Use the host's pid namespace.", - }, - - "hostname": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "Specifies the hostname of the Pod If not specified, the pod's hostname will be set to a system-defined value.", - }, - "image_pull_secrets": { - Type: schema.TypeList, - Description: "ImagePullSecrets is an optional list of references to secrets in the same namespace to use for pulling any of the images used by this PodSpec. If specified, these secrets will be passed to individual puller implementations for them to use. For example, in the case of docker, only DockerConfig type secrets are honored. More info: http://kubernetes.io/docs/user-guide/images#specifying-imagepullsecrets-on-a-pod", - Optional: true, - Computed: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Required: true, - }, - }, - }, - }, - "node_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "NodeName is a request to schedule this pod onto a specific node. If it is non-empty, the scheduler simply schedules this pod onto that node, assuming that it fits resource requirements.", - }, - "node_selector": { - Type: schema.TypeMap, - Optional: true, - Description: "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: http://kubernetes.io/docs/user-guide/node-selection.", - }, - "restart_policy": { - Type: schema.TypeString, - Optional: true, - Default: "Always", - Description: "Restart policy for all containers within the pod. One of Always, OnFailure, Never. More info: http://kubernetes.io/docs/user-guide/pod-states#restartpolicy.", - }, - "security_context": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_group": { - Type: schema.TypeInt, - Description: "A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- If unset, the Kubelet will not modify the ownership and permissions of any volume.", - Optional: true, - }, - "run_as_non_root": { - Type: schema.TypeBool, - Description: "Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does.", - Optional: true, - }, - "run_as_user": { - Type: schema.TypeInt, - Description: "The UID to run the entrypoint of the container process. Defaults to user specified in image metadata if unspecified", - Optional: true, - }, - "supplemental_groups": { - Type: schema.TypeSet, - Description: "A list of groups applied to the first process run in each container, in addition to the container's primary GID. If unspecified, no groups will be added to any container.", - Optional: true, - Elem: &schema.Schema{ - Type: schema.TypeInt, - }, - }, - "se_linux_options": { - Type: schema.TypeList, - Description: "The SELinux context to be applied to all containers. If unspecified, the container runtime will allocate a random SELinux context for each container. May also be set in SecurityContext. If set in both SecurityContext and PodSecurityContext, the value specified in SecurityContext takes precedence for that container.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: seLinuxOptionsField(), - }, - }, - }, - }, - }, - "service_account_name": { - Type: schema.TypeString, - Optional: true, - Computed: true, - Description: "ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: http://releases.k8s.io/HEAD/docs/design/service_accounts.md.", - }, - "subdomain": { - Type: schema.TypeString, - Optional: true, - Description: `If specified, the fully qualified Pod hostname will be "...svc.". If not specified, the pod will not have a domainname at all..`, - }, - "termination_grace_period_seconds": { - Type: schema.TypeInt, - Optional: true, - Default: 30, - ValidateFunc: validateTerminationGracePeriodSeconds, - Description: "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process.", - }, - - "volume": { - Type: schema.TypeList, - Optional: true, - Description: "List of volumes that can be mounted by containers belonging to the pod. More info: http://kubernetes.io/docs/user-guide/volumes", - Elem: volumeSchema(), - }, - } - - if !isUpdatable { - for k, _ := range s { - if k == "active_deadline_seconds" { - // This field is always updatable - continue - } - if k == "container" { - // Some fields are always updatable - continue - } - s[k].ForceNew = true - } - } - - return s -} - -func volumeSchema() *schema.Resource { - v := commonVolumeSources() - - v["config_map"] = &schema.Schema{ - Type: schema.TypeList, - Description: "ConfigMap represents a configMap that should populate this volume", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "items": { - Type: schema.TypeList, - Description: `If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.`, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Optional: true, - Description: "The key to project.", - }, - "mode": { - Type: schema.TypeInt, - Optional: true, - Description: `Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.`, - }, - "path": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateAttributeValueDoesNotContain(".."), - Description: `The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'.`, - }, - }, - }, - }, - "default_mode": { - Type: schema.TypeInt, - Description: "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", - Optional: true, - ValidateFunc: validateModeBits, - }, - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - } - - v["git_repo"] = &schema.Schema{ - Type: schema.TypeList, - Description: "GitRepo represents a git repository at a particular revision.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "directory": { - Type: schema.TypeString, - Description: "Target directory name. Must not contain or start with '..'. If '.' is supplied, the volume directory will be the git repository. Otherwise, if specified, the volume will contain the git repository in the subdirectory with the given name.", - Optional: true, - ValidateFunc: validateAttributeValueDoesNotContain(".."), - }, - "repository": { - Type: schema.TypeString, - Description: "Repository URL", - Optional: true, - }, - "revision": { - Type: schema.TypeString, - Description: "Commit hash for the specified revision.", - Optional: true, - }, - }, - }, - } - v["downward_api"] = &schema.Schema{ - Type: schema.TypeList, - Description: "DownwardAPI represents downward API about the pod that should populate this volume", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "default_mode": { - Type: schema.TypeInt, - Description: "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", - Optional: true, - }, - "items": { - Type: schema.TypeList, - Description: `If unspecified, each key-value pair in the Data field of the referenced ConfigMap will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the ConfigMap, the volume setup will error. Paths must be relative and may not contain the '..' path or start with '..'.`, - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "field_ref": { - Type: schema.TypeList, - Required: true, - MaxItems: 1, - Description: "Required: Selects a field of the pod: only annotations, labels, name and namespace are supported.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "api_version": { - Type: schema.TypeString, - Optional: true, - Default: "v1", - Description: `Version of the schema the FieldPath is written in terms of, defaults to "v1".`, - }, - "field_path": { - Type: schema.TypeString, - Optional: true, - Description: "Path of the field to select in the specified API version", - }, - }, - }, - }, - "mode": { - Type: schema.TypeInt, - Optional: true, - Description: `Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.`, - }, - "path": { - Type: schema.TypeString, - Required: true, - ValidateFunc: validateAttributeValueDoesNotContain(".."), - Description: `Path is the relative path name of the file to be created. Must not be absolute or contain the '..' path. Must be utf-8 encoded. The first item of the relative path must not start with '..'`, - }, - "resource_field_ref": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: "Selects a resource of the container: only resources limits and requests (limits.cpu, limits.memory, requests.cpu and requests.memory) are currently supported.", - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "container_name": { - Type: schema.TypeString, - Required: true, - }, - "quantity": { - Type: schema.TypeString, - Optional: true, - }, - "resource": { - Type: schema.TypeString, - Required: true, - Description: "Resource to select", - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - v["empty_dir"] = &schema.Schema{ - Type: schema.TypeList, - Description: "EmptyDir represents a temporary directory that shares a pod's lifetime. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "medium": { - Type: schema.TypeString, - Description: `What type of storage medium should back this directory. The default is "" which means to use the node's default medium. Must be an empty string (default) or Memory. More info: http://kubernetes.io/docs/user-guide/volumes#emptydir`, - Optional: true, - Default: "", - ValidateFunc: validateAttributeValueIsIn([]string{"", "Memory"}), - }, - }, - }, - } - - v["persistent_volume_claim"] = &schema.Schema{ - Type: schema.TypeList, - Description: "The specification of a persistent volume.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "claim_name": { - Type: schema.TypeString, - Description: "ClaimName is the name of a PersistentVolumeClaim in the same ", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Will force the ReadOnly setting in VolumeMounts.", - Optional: true, - Default: false, - }, - }, - }, - } - - v["secret"] = &schema.Schema{ - Type: schema.TypeList, - Description: "Secret represents a secret that should populate this volume. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "default_mode": { - Type: schema.TypeInt, - Description: "Optional: mode bits to use on created files by default. Must be a value between 0 and 0777. Defaults to 0644. Directories within the path are not affected by this setting. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", - Optional: true, - Default: 0644, - ValidateFunc: validateModeBits, - }, - "items": { - Type: schema.TypeList, - Description: "If unspecified, each key-value pair in the Data field of the referenced Secret will be projected into the volume as a file whose name is the key and content is the value. If specified, the listed keys will be projected into the specified paths, and unlisted keys will not be present. If a key is specified which is not present in the Secret, the volume setup will error unless it is marked optional. Paths must be relative and may not contain the '..' path or start with '..'.", - Optional: true, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "key": { - Type: schema.TypeString, - Optional: true, - Description: "The key to project.", - }, - "mode": { - Type: schema.TypeInt, - Optional: true, - Description: "Optional: mode bits to use on this file, must be a value between 0 and 0777. If not specified, the volume defaultMode will be used. This might be in conflict with other options that affect the file mode, like fsGroup, and the result can be other mode bits set.", - }, - "path": { - Type: schema.TypeString, - Optional: true, - ValidateFunc: validateAttributeValueDoesNotContain(".."), - Description: "The relative path of the file to map the key to. May not be an absolute path. May not contain the path element '..'. May not start with the string '..'.", - }, - }, - }, - }, - "optional": { - Type: schema.TypeBool, - Description: "Optional: Specify whether the Secret or it's keys must be defined.", - Optional: true, - }, - "secret_name": { - Type: schema.TypeString, - Description: "Name of the secret in the pod's namespace to use. More info: http://kubernetes.io/docs/user-guide/volumes#secrets", - Optional: true, - }, - }, - }, - } - v["name"] = &schema.Schema{ - Type: schema.TypeString, - Description: "Volume's name. Must be a DNS_LABEL and unique within the pod. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - } - return &schema.Resource{ - Schema: v, - } -} diff --git a/kubernetes/schema_rbac.go b/kubernetes/schema_rbac.go deleted file mode 100644 index a130e7556e..0000000000 --- a/kubernetes/schema_rbac.go +++ /dev/null @@ -1,54 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" -) - -func rbacRoleRefSchema(kind string) map[string]*schema.Schema { - return map[string]*schema.Schema{ - "api_group": { - Type: schema.TypeString, - Description: "The API group of the user. Always `rbac.authorization.k8s.io`", - Required: true, - Default: "rbac.authorization.k8s.io", - }, - "kind": { - Type: schema.TypeString, - Description: "The kind of resource.", - Default: kind, - Required: true, - }, - "name": { - Type: schema.TypeString, - Description: "The name of the User to bind to.", - Required: true, - }, - } -} - -func rbacSubjectSchema() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "api_group": { - Type: schema.TypeString, - Description: "The API group of the user. Always `rbac.authorization.k8s.io`", - Optional: true, - Default: "rbac.authorization.k8s.io", - }, - "kind": { - Type: schema.TypeString, - Description: "The kind of resource.", - Required: true, - }, - "name": { - Type: schema.TypeString, - Description: "The name of the resource to bind to.", - Required: true, - }, - "namespace": { - Type: schema.TypeString, - Description: "The Namespace of the ServiceAccount", - Optional: true, - Default: "default", - }, - } -} diff --git a/kubernetes/schema_volume_source.go b/kubernetes/schema_volume_source.go deleted file mode 100644 index 008960ba35..0000000000 --- a/kubernetes/schema_volume_source.go +++ /dev/null @@ -1,559 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" -) - -func persistentVolumeSourceSchema() *schema.Resource { - return &schema.Resource{ - Schema: commonVolumeSources(), - } -} - -// Common volume sources between Persistent Volumes and Pod Volumes -func commonVolumeSources() map[string]*schema.Schema { - return map[string]*schema.Schema{ - "host_path": { - Type: schema.TypeList, - Description: "Represents a directory on the host. Provisioned by a developer or tester. This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster. More info: http://kubernetes.io/docs/user-guide/volumes#hostpath", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "path": { - Type: schema.TypeString, - Description: "Path of the directory on the host. More info: http://kubernetes.io/docs/user-guide/volumes#hostpath", - Optional: true, - }, - }, - }, - }, - "aws_elastic_block_store": { - Type: schema.TypeList, - Description: "Represents an AWS Disk resource that is attached to a kubelet's host machine and then exposed to the pod. More info: http://kubernetes.io/docs/user-guide/volumes#awselasticblockstore", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: http://kubernetes.io/docs/user-guide/volumes#awselasticblockstore", - Optional: true, - }, - "partition": { - Type: schema.TypeInt, - Description: "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty).", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to set the read-only property in VolumeMounts to \"true\". If omitted, the default is \"false\". More info: http://kubernetes.io/docs/user-guide/volumes#awselasticblockstore", - Optional: true, - }, - "volume_id": { - Type: schema.TypeString, - Description: "Unique ID of the persistent disk resource in AWS (Amazon EBS volume). More info: http://kubernetes.io/docs/user-guide/volumes#awselasticblockstore", - Required: true, - }, - }, - }, - }, - "azure_disk": { - Type: schema.TypeList, - Description: "Represents an Azure Data Disk mount on the host and bind mount to the pod.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "caching_mode": { - Type: schema.TypeString, - Description: "Host Caching mode: None, Read Only, Read Write.", - Required: true, - }, - "data_disk_uri": { - Type: schema.TypeString, - Description: "The URI the data disk in the blob storage", - Required: true, - }, - "disk_name": { - Type: schema.TypeString, - Description: "The Name of the data disk in the blob storage", - Required: true, - }, - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false (read/write).", - Optional: true, - Default: false, - }, - }, - }, - }, - "azure_file": { - Type: schema.TypeList, - Description: "Represents an Azure File Service mount on the host and bind mount to the pod.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false (read/write).", - Optional: true, - }, - "secret_name": { - Type: schema.TypeString, - Description: "The name of secret that contains Azure Storage Account Name and Key", - Required: true, - }, - "share_name": { - Type: schema.TypeString, - Description: "Share Name", - Required: true, - }, - }, - }, - }, - "ceph_fs": { - Type: schema.TypeList, - Description: "Represents a Ceph FS mount on the host that shares a pod's lifetime", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "monitors": { - Type: schema.TypeSet, - Description: "Monitors is a collection of Ceph monitors More info: http://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "path": { - Type: schema.TypeString, - Description: "Used as the mounted root, rather than the full Ceph tree, default is /", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to `false` (read/write). More info: http://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", - Optional: true, - }, - "secret_file": { - Type: schema.TypeString, - Description: "The path to key ring for User, default is /etc/ceph/user.secret More info: http://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", - Optional: true, - }, - "secret_ref": { - Type: schema.TypeList, - Description: "Reference to the authentication secret for User, default is empty. More info: http://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - }, - "user": { - Type: schema.TypeString, - Description: "User is the rados user name, default is admin. More info: http://releases.k8s.io/HEAD/examples/volumes/cephfs/README.md#how-to-use-it", - Optional: true, - }, - }, - }, - }, - "cinder": { - Type: schema.TypeList, - Description: "Represents a cinder volume attached and mounted on kubelets host machine. More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false (read/write). More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - Optional: true, - }, - "volume_id": { - Type: schema.TypeString, - Description: "Volume ID used to identify the volume in Cinder. More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md", - Required: true, - }, - }, - }, - }, - "fc": { - Type: schema.TypeList, - Description: "Represents a Fibre Channel resource that is attached to a kubelet's host machine and then exposed to the pod.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", - Optional: true, - }, - "lun": { - Type: schema.TypeInt, - Description: "FC target lun number", - Required: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false (read/write).", - Optional: true, - }, - "target_ww_ns": { - Type: schema.TypeSet, - Description: "FC target worldwide names (WWNs)", - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - }, - }, - }, - "flex_volume": { - Type: schema.TypeList, - Description: "Represents a generic volume resource that is provisioned/attached using an exec based plugin. This is an alpha feature and may change in future.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "driver": { - Type: schema.TypeString, - Description: "Driver is the name of the driver to use for this volume.", - Required: true, - }, - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". The default filesystem depends on FlexVolume script.", - Optional: true, - }, - "options": { - Type: schema.TypeMap, - Description: "Extra command options if any.", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the ReadOnly setting in VolumeMounts. Defaults to false (read/write).", - Optional: true, - }, - "secret_ref": { - Type: schema.TypeList, - Description: "Reference to the secret object containing sensitive information to pass to the plugin scripts. This may be empty if no secret object is specified. If the secret object contains more than one secret, all secrets are passed to the plugin scripts.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - }, - }, - }, - }, - "flocker": { - Type: schema.TypeList, - Description: "Represents a Flocker volume attached to a kubelet's host machine and exposed to the pod for its usage. This depends on the Flocker control service being running", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "dataset_name": { - Type: schema.TypeString, - Description: "Name of the dataset stored as metadata -> name on the dataset for Flocker should be considered as deprecated", - Optional: true, - }, - "dataset_uuid": { - Type: schema.TypeString, - Description: "UUID of the dataset. This is unique identifier of a Flocker dataset", - Optional: true, - }, - }, - }, - }, - "gce_persistent_disk": { - Type: schema.TypeList, - Description: "Represents a GCE Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin. More info: http://kubernetes.io/docs/user-guide/volumes#gcepersistentdisk", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: http://kubernetes.io/docs/user-guide/volumes#gcepersistentdisk", - Optional: true, - }, - "partition": { - Type: schema.TypeInt, - Description: "The partition in the volume that you want to mount. If omitted, the default is to mount by volume name. Examples: For volume /dev/sda1, you specify the partition as \"1\". Similarly, the volume partition for /dev/sda is \"0\" (or you can leave the property empty). More info: http://kubernetes.io/docs/user-guide/volumes#gcepersistentdisk", - Optional: true, - }, - "pd_name": { - Type: schema.TypeString, - Description: "Unique name of the PD resource in GCE. Used to identify the disk in GCE. More info: http://kubernetes.io/docs/user-guide/volumes#gcepersistentdisk", - Required: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the ReadOnly setting in VolumeMounts. Defaults to false. More info: http://kubernetes.io/docs/user-guide/volumes#gcepersistentdisk", - Optional: true, - }, - }, - }, - }, - "glusterfs": { - Type: schema.TypeList, - Description: "Represents a Glusterfs volume that is attached to a host and exposed to the pod. Provisioned by an admin. More info: http://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "endpoints_name": { - Type: schema.TypeString, - Description: "The endpoint name that details Glusterfs topology. More info: http://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", - Required: true, - }, - "path": { - Type: schema.TypeString, - Description: "The Glusterfs volume path. More info: http://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", - Required: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the Glusterfs volume to be mounted with read-only permissions. Defaults to false. More info: http://releases.k8s.io/HEAD/examples/volumes/glusterfs/README.md#create-a-pod", - Optional: true, - }, - }, - }, - }, - "iscsi": { - Type: schema.TypeList, - Description: "Represents an ISCSI Disk resource that is attached to a kubelet's host machine and then exposed to the pod. Provisioned by an admin.", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: http://kubernetes.io/docs/user-guide/volumes#iscsi", - Optional: true, - }, - "iqn": { - Type: schema.TypeString, - Description: "Target iSCSI Qualified Name.", - Required: true, - }, - "iscsi_interface": { - Type: schema.TypeString, - Description: "iSCSI interface name that uses an iSCSI transport. Defaults to 'default' (tcp).", - Optional: true, - Default: "default", - }, - "lun": { - Type: schema.TypeInt, - Description: "iSCSI target lun number.", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false.", - Optional: true, - }, - "target_portal": { - Type: schema.TypeString, - Description: "iSCSI target portal. The portal is either an IP or ip_addr:port if the port is other than default (typically TCP ports 860 and 3260).", - Required: true, - }, - }, - }, - }, - "nfs": { - Type: schema.TypeList, - Description: "Represents an NFS mount on the host. Provisioned by an admin. More info: http://kubernetes.io/docs/user-guide/volumes#nfs", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "path": { - Type: schema.TypeString, - Description: "Path that is exported by the NFS server. More info: http://kubernetes.io/docs/user-guide/volumes#nfs", - Required: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the NFS export to be mounted with read-only permissions. Defaults to false. More info: http://kubernetes.io/docs/user-guide/volumes#nfs", - Optional: true, - }, - "server": { - Type: schema.TypeString, - Description: "Server is the hostname or IP address of the NFS server. More info: http://kubernetes.io/docs/user-guide/volumes#nfs", - Required: true, - }, - }, - }, - }, - "photon_persistent_disk": { - Type: schema.TypeList, - Description: "Represents a PhotonController persistent disk attached and mounted on kubelets host machine", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", - Optional: true, - }, - "pd_id": { - Type: schema.TypeString, - Description: "ID that identifies Photon Controller persistent disk", - Required: true, - }, - }, - }, - }, - "quobyte": { - Type: schema.TypeList, - Description: "Quobyte represents a Quobyte mount on the host that shares a pod's lifetime", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "group": { - Type: schema.TypeString, - Description: "Group to map volume access to Default is no group", - Optional: true, - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the Quobyte volume to be mounted with read-only permissions. Defaults to false.", - Optional: true, - }, - "registry": { - Type: schema.TypeString, - Description: "Registry represents a single or multiple Quobyte Registry services specified as a string as host:port pair (multiple entries are separated with commas) which acts as the central registry for volumes", - Required: true, - }, - "user": { - Type: schema.TypeString, - Description: "User to map volume access to Defaults to serivceaccount user", - Optional: true, - }, - "volume": { - Type: schema.TypeString, - Description: "Volume is a string that references an already created Quobyte volume by name.", - Required: true, - }, - }, - }, - }, - "rbd": { - Type: schema.TypeList, - Description: "Represents a Rados Block Device mount on the host that shares a pod's lifetime. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "ceph_monitors": { - Type: schema.TypeSet, - Description: "A collection of Ceph monitors. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Required: true, - Elem: &schema.Schema{Type: schema.TypeString}, - Set: schema.HashString, - }, - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type of the volume that you want to mount. Tip: Ensure that the filesystem type is supported by the host operating system. Examples: \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified. More info: http://kubernetes.io/docs/user-guide/volumes#rbd", - Optional: true, - }, - "keyring": { - Type: schema.TypeString, - Description: "Keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Optional: true, - Computed: true, - }, - "rados_user": { - Type: schema.TypeString, - Description: "The rados user name. Default is admin. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Optional: true, - Default: "admin", - }, - "rbd_image": { - Type: schema.TypeString, - Description: "The rados image name. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Required: true, - }, - "rbd_pool": { - Type: schema.TypeString, - Description: "The rados pool name. Default is rbd. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it.", - Optional: true, - Default: "rbd", - }, - "read_only": { - Type: schema.TypeBool, - Description: "Whether to force the read-only setting in VolumeMounts. Defaults to false. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Optional: true, - Default: false, - }, - "secret_ref": { - Type: schema.TypeList, - Description: "Name of the authentication secret for RBDUser. If provided overrides keyring. Default is nil. More info: http://releases.k8s.io/HEAD/examples/volumes/rbd/README.md#how-to-use-it", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "name": { - Type: schema.TypeString, - Description: "Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names", - Optional: true, - }, - }, - }, - }, - }, - }, - }, - "vsphere_volume": { - Type: schema.TypeList, - Description: "Represents a vSphere volume attached and mounted on kubelets host machine", - Optional: true, - MaxItems: 1, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "fs_type": { - Type: schema.TypeString, - Description: "Filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. \"ext4\", \"xfs\", \"ntfs\". Implicitly inferred to be \"ext4\" if unspecified.", - Optional: true, - }, - "volume_path": { - Type: schema.TypeString, - Description: "Path that identifies vSphere volume vmdk", - Required: true, - }, - }, - }, - }, - } -} diff --git a/kubernetes/structure_horizontal_pod_autoscaler.go b/kubernetes/structure_horizontal_pod_autoscaler.go deleted file mode 100644 index 80fccde28d..0000000000 --- a/kubernetes/structure_horizontal_pod_autoscaler.go +++ /dev/null @@ -1,105 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/autoscaling/v1" -) - -func expandHorizontalPodAutoscalerSpec(in []interface{}) api.HorizontalPodAutoscalerSpec { - if len(in) == 0 || in[0] == nil { - return api.HorizontalPodAutoscalerSpec{} - } - spec := api.HorizontalPodAutoscalerSpec{} - m := in[0].(map[string]interface{}) - if v, ok := m["max_replicas"]; ok { - spec.MaxReplicas = int32(v.(int)) - } - if v, ok := m["min_replicas"].(int); ok && v > 0 { - spec.MinReplicas = ptrToInt32(int32(v)) - } - if v, ok := m["scale_target_ref"]; ok { - spec.ScaleTargetRef = expandCrossVersionObjectReference(v.([]interface{})) - } - if v, ok := m["target_cpu_utilization_percentage"].(int); ok && v > 0 { - spec.TargetCPUUtilizationPercentage = ptrToInt32(int32(v)) - } - - return spec -} - -func expandCrossVersionObjectReference(in []interface{}) api.CrossVersionObjectReference { - if len(in) == 0 || in[0] == nil { - return api.CrossVersionObjectReference{} - } - ref := api.CrossVersionObjectReference{} - m := in[0].(map[string]interface{}) - - if v, ok := m["api_version"]; ok { - ref.APIVersion = v.(string) - } - if v, ok := m["kind"]; ok { - ref.Kind = v.(string) - } - if v, ok := m["name"]; ok { - ref.Name = v.(string) - } - return ref -} - -func flattenHorizontalPodAutoscalerSpec(spec api.HorizontalPodAutoscalerSpec) []interface{} { - m := make(map[string]interface{}, 0) - m["max_replicas"] = spec.MaxReplicas - if spec.MinReplicas != nil { - m["min_replicas"] = *spec.MinReplicas - } - m["scale_target_ref"] = flattenCrossVersionObjectReference(spec.ScaleTargetRef) - if spec.TargetCPUUtilizationPercentage != nil { - m["target_cpu_utilization_percentage"] = *spec.TargetCPUUtilizationPercentage - } - return []interface{}{m} -} - -func flattenCrossVersionObjectReference(ref api.CrossVersionObjectReference) []interface{} { - m := make(map[string]interface{}, 0) - if ref.APIVersion != "" { - m["api_version"] = ref.APIVersion - } - if ref.Kind != "" { - m["kind"] = ref.Kind - } - if ref.Name != "" { - m["name"] = ref.Name - } - return []interface{}{m} -} - -func patchHorizontalPodAutoscalerSpec(prefix string, pathPrefix string, d *schema.ResourceData) []PatchOperation { - ops := make([]PatchOperation, 0) - - if d.HasChange(prefix + "max_replicas") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/maxReplicas", - Value: d.Get(prefix + "max_replicas").(int), - }) - } - if d.HasChange(prefix + "min_replicas") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/minReplicas", - Value: d.Get(prefix + "min_replicas").(int), - }) - } - if d.HasChange(prefix + "scale_target_ref") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/scaleTargetRef", - Value: expandCrossVersionObjectReference(d.Get(prefix + "scale_target_ref").([]interface{})), - }) - } - if d.HasChange(prefix + "target_cpu_utilization_percentage") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/targetCPUUtilizationPercentage", - Value: d.Get(prefix + "target_cpu_utilization_percentage").(int), - }) - } - - return ops -} diff --git a/kubernetes/structure_label_selector.go b/kubernetes/structure_label_selector.go deleted file mode 100644 index c01f3f3751..0000000000 --- a/kubernetes/structure_label_selector.go +++ /dev/null @@ -1,67 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// Flatteners - -func flattenLabelSelector(in *metav1.LabelSelector) []interface{} { - att := make(map[string]interface{}) - if len(in.MatchLabels) > 0 { - att["match_labels"] = in.MatchLabels - } - if len(in.MatchExpressions) > 0 { - att["match_expressions"] = flattenLabelSelectorRequirement(in.MatchExpressions) - } - if len(att) > 0 { - return []interface{}{att} - } - return []interface{}{} -} - -func flattenLabelSelectorRequirement(in []metav1.LabelSelectorRequirement) []interface{} { - att := make([]interface{}, len(in), len(in)) - for i, n := range in { - m := make(map[string]interface{}) - m["key"] = n.Key - m["operator"] = n.Operator - m["values"] = newStringSet(schema.HashString, n.Values) - att[i] = m - } - return att -} - -// Expanders - -func expandLabelSelector(l []interface{}) *metav1.LabelSelector { - if len(l) == 0 || l[0] == nil { - return &metav1.LabelSelector{} - } - in := l[0].(map[string]interface{}) - obj := &metav1.LabelSelector{} - if v, ok := in["match_labels"].(map[string]interface{}); ok && len(v) > 0 { - obj.MatchLabels = expandStringMap(v) - } - if v, ok := in["match_expressions"].([]interface{}); ok && len(v) > 0 { - obj.MatchExpressions = expandLabelSelectorRequirement(v) - } - return obj -} - -func expandLabelSelectorRequirement(l []interface{}) []metav1.LabelSelectorRequirement { - if len(l) == 0 || l[0] == nil { - return []metav1.LabelSelectorRequirement{} - } - obj := make([]metav1.LabelSelectorRequirement, len(l), len(l)) - for i, n := range l { - in := n.(map[string]interface{}) - obj[i] = metav1.LabelSelectorRequirement{ - Key: in["key"].(string), - Operator: metav1.LabelSelectorOperator(in["operator"].(string)), - Values: sliceOfString(in["values"].(*schema.Set).List()), - } - } - return obj -} diff --git a/kubernetes/structure_label_selector_test.go b/kubernetes/structure_label_selector_test.go deleted file mode 100644 index e58b13b42c..0000000000 --- a/kubernetes/structure_label_selector_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package kubernetes - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "reflect" - "testing" -) - -func TestFlattenLabelSelector(t *testing.T) { - cases := []struct { - Input *metav1.LabelSelector - ExpectedOutput []interface{} - }{ - { - &metav1.LabelSelector{MatchLabels: map[string]string{"key": "value"}}, - []interface{}{ - map[string]interface{}{ - "match_labels": map[string]string{"key": "value"}, - }, - }, - }, - { - &metav1.LabelSelector{}, - []interface{}{}, - }, - } - - for _, tc := range cases { - output := flattenLabelSelector(tc.Input) - if !reflect.DeepEqual(output, tc.ExpectedOutput) { - t.Fatalf("Unexpected output from flattener.\nExpected: %#v\nGiven: %#v", - tc.ExpectedOutput, output) - } - } -} diff --git a/kubernetes/structure_persistent_volume_claim.go b/kubernetes/structure_persistent_volume_claim.go deleted file mode 100644 index b7bca38a35..0000000000 --- a/kubernetes/structure_persistent_volume_claim.go +++ /dev/null @@ -1,85 +0,0 @@ -package kubernetes - -import ( - "github.com/hashicorp/terraform/helper/schema" - "k8s.io/api/core/v1" -) - -// Flatteners - -func flattenPersistentVolumeClaimSpec(in v1.PersistentVolumeClaimSpec) []interface{} { - att := make(map[string]interface{}) - att["access_modes"] = flattenPersistentVolumeAccessModes(in.AccessModes) - att["resources"] = flattenResourceRequirements(in.Resources) - if in.Selector != nil { - att["selector"] = flattenLabelSelector(in.Selector) - } - if in.VolumeName != "" { - att["volume_name"] = in.VolumeName - } - if in.StorageClassName != nil { - att["storage_class_name"] = *in.StorageClassName - } - return []interface{}{att} -} - -func flattenResourceRequirements(in v1.ResourceRequirements) []interface{} { - att := make(map[string]interface{}) - if len(in.Limits) > 0 { - att["limits"] = flattenResourceList(in.Limits) - } - if len(in.Requests) > 0 { - att["requests"] = flattenResourceList(in.Requests) - } - return []interface{}{att} -} - -// Expanders - -func expandPersistentVolumeClaimSpec(l []interface{}) (v1.PersistentVolumeClaimSpec, error) { - if len(l) == 0 || l[0] == nil { - return v1.PersistentVolumeClaimSpec{}, nil - } - in := l[0].(map[string]interface{}) - resourceRequirements, err := expandResourceRequirements(in["resources"].([]interface{})) - if err != nil { - return v1.PersistentVolumeClaimSpec{}, err - } - obj := v1.PersistentVolumeClaimSpec{ - AccessModes: expandPersistentVolumeAccessModes(in["access_modes"].(*schema.Set).List()), - Resources: resourceRequirements, - } - if v, ok := in["selector"].([]interface{}); ok && len(v) > 0 { - obj.Selector = expandLabelSelector(v) - } - if v, ok := in["volume_name"].(string); ok { - obj.VolumeName = v - } - if v, ok := in["storage_class_name"].(string); ok && v != "" { - obj.StorageClassName = ptrToString(v) - } - return obj, nil -} - -func expandResourceRequirements(l []interface{}) (v1.ResourceRequirements, error) { - if len(l) == 0 || l[0] == nil { - return v1.ResourceRequirements{}, nil - } - in := l[0].(map[string]interface{}) - obj := v1.ResourceRequirements{} - if v, ok := in["limits"].(map[string]interface{}); ok && len(v) > 0 { - var err error - obj.Limits, err = expandMapToResourceList(v) - if err != nil { - return obj, err - } - } - if v, ok := in["requests"].(map[string]interface{}); ok && len(v) > 0 { - var err error - obj.Requests, err = expandMapToResourceList(v) - if err != nil { - return obj, err - } - } - return obj, nil -} diff --git a/kubernetes/structure_persistent_volume_spec.go b/kubernetes/structure_persistent_volume_spec.go deleted file mode 100644 index 697d469f0b..0000000000 --- a/kubernetes/structure_persistent_volume_spec.go +++ /dev/null @@ -1,1413 +0,0 @@ -package kubernetes - -import ( - "k8s.io/api/core/v1" - - "github.com/hashicorp/terraform/helper/schema" -) - -// Flatteners - -func flattenAWSElasticBlockStoreVolumeSource(in *v1.AWSElasticBlockStoreVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["volume_id"] = in.VolumeID - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.Partition != 0 { - att["partition"] = in.Partition - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenAzureDiskVolumeSource(in *v1.AzureDiskVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["disk_name"] = in.DiskName - att["data_disk_uri"] = in.DataDiskURI - att["caching_mode"] = string(*in.CachingMode) - if in.FSType != nil { - att["fs_type"] = *in.FSType - } - if in.ReadOnly != nil { - att["read_only"] = *in.ReadOnly - } - return []interface{}{att} -} - -func flattenAzureFileVolumeSource(in *v1.AzureFileVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["secret_name"] = in.SecretName - att["share_name"] = in.ShareName - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenAzureFilePersistentVolumeSource(in *v1.AzureFilePersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["secret_name"] = in.SecretName - att["share_name"] = in.ShareName - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenCephFSVolumeSource(in *v1.CephFSVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["monitors"] = newStringSet(schema.HashString, in.Monitors) - if in.Path != "" { - att["path"] = in.Path - } - if in.User != "" { - att["user"] = in.User - } - if in.SecretFile != "" { - att["secret_file"] = in.SecretFile - } - if in.SecretRef != nil { - att["secret_ref"] = flattenLocalObjectReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenCephFSPersistentVolumeSource(in *v1.CephFSPersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["monitors"] = newStringSet(schema.HashString, in.Monitors) - if in.Path != "" { - att["path"] = in.Path - } - if in.User != "" { - att["user"] = in.User - } - if in.SecretFile != "" { - att["secret_file"] = in.SecretFile - } - if in.SecretRef != nil { - att["secret_ref"] = flattenSecretReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenCinderVolumeSource(in *v1.CinderVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["volume_id"] = in.VolumeID - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenFCVolumeSource(in *v1.FCVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["target_ww_ns"] = newStringSet(schema.HashString, in.TargetWWNs) - att["lun"] = *in.Lun - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenFlexPersistentVolumeSource(in *v1.FlexPersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["driver"] = in.Driver - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.SecretRef != nil { - att["secret_ref"] = flattenSecretReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - if len(in.Options) > 0 { - att["options"] = in.Options - } - return []interface{}{att} -} - -func flattenFlexVolumeSource(in *v1.FlexVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["driver"] = in.Driver - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.SecretRef != nil { - att["secret_ref"] = flattenLocalObjectReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - if len(in.Options) > 0 { - att["options"] = in.Options - } - return []interface{}{att} -} - -func flattenFlockerVolumeSource(in *v1.FlockerVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["dataset_name"] = in.DatasetName - att["dataset_uuid"] = in.DatasetUUID - return []interface{}{att} -} - -func flattenGCEPersistentDiskVolumeSource(in *v1.GCEPersistentDiskVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["pd_name"] = in.PDName - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.Partition != 0 { - att["partition"] = in.Partition - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenGlusterfsVolumeSource(in *v1.GlusterfsVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["endpoints_name"] = in.EndpointsName - att["path"] = in.Path - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenHostPathVolumeSource(in *v1.HostPathVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["path"] = in.Path - return []interface{}{att} -} - -func flattenISCSIVolumeSource(in *v1.ISCSIVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.TargetPortal != "" { - att["target_portal"] = in.TargetPortal - } - if in.IQN != "" { - att["iqn"] = in.IQN - } - if in.Lun != 0 { - att["lun"] = in.Lun - } - if in.ISCSIInterface != "" { - att["iscsi_interface"] = in.ISCSIInterface - } - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenISCSIPersistentVolumeSource(in *v1.ISCSIPersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.TargetPortal != "" { - att["target_portal"] = in.TargetPortal - } - if in.IQN != "" { - att["iqn"] = in.IQN - } - if in.Lun != 0 { - att["lun"] = in.Lun - } - if in.ISCSIInterface != "" { - att["iscsi_interface"] = in.ISCSIInterface - } - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenLocalObjectReference(in *v1.LocalObjectReference) []interface{} { - att := make(map[string]interface{}) - if in.Name != "" { - att["name"] = in.Name - } - return []interface{}{att} -} - -func flattenSecretReference(in *v1.SecretReference) []interface{} { - att := make(map[string]interface{}) - if in.Name != "" { - att["name"] = in.Name - } - return []interface{}{att} -} - -func flattenNFSVolumeSource(in *v1.NFSVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["server"] = in.Server - att["path"] = in.Path - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenPersistentVolumeSource(in v1.PersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.GCEPersistentDisk != nil { - att["gce_persistent_disk"] = flattenGCEPersistentDiskVolumeSource(in.GCEPersistentDisk) - } - if in.AWSElasticBlockStore != nil { - att["aws_elastic_block_store"] = flattenAWSElasticBlockStoreVolumeSource(in.AWSElasticBlockStore) - } - if in.HostPath != nil { - att["host_path"] = flattenHostPathVolumeSource(in.HostPath) - } - if in.Glusterfs != nil { - att["glusterfs"] = flattenGlusterfsVolumeSource(in.Glusterfs) - } - if in.NFS != nil { - att["nfs"] = flattenNFSVolumeSource(in.NFS) - } - if in.RBD != nil { - att["rbd"] = flattenRBDPersistentVolumeSource(in.RBD) - } - if in.ISCSI != nil { - att["iscsi"] = flattenISCSIPersistentVolumeSource(in.ISCSI) - } - if in.Cinder != nil { - att["cinder"] = flattenCinderVolumeSource(in.Cinder) - } - if in.CephFS != nil { - att["ceph_fs"] = flattenCephFSPersistentVolumeSource(in.CephFS) - } - if in.FC != nil { - att["fc"] = flattenFCVolumeSource(in.FC) - } - if in.Flocker != nil { - att["flocker"] = flattenFlockerVolumeSource(in.Flocker) - } - if in.FlexVolume != nil { - att["flex_volume"] = flattenFlexPersistentVolumeSource(in.FlexVolume) - } - if in.AzureFile != nil { - att["azure_file"] = flattenAzureFilePersistentVolumeSource(in.AzureFile) - } - if in.VsphereVolume != nil { - att["vsphere_volume"] = flattenVsphereVirtualDiskVolumeSource(in.VsphereVolume) - } - if in.Quobyte != nil { - att["quobyte"] = flattenQuobyteVolumeSource(in.Quobyte) - } - if in.AzureDisk != nil { - att["azure_disk"] = flattenAzureDiskVolumeSource(in.AzureDisk) - } - if in.PhotonPersistentDisk != nil { - att["photon_persistent_disk"] = flattenPhotonPersistentDiskVolumeSource(in.PhotonPersistentDisk) - } - return []interface{}{att} -} - -func flattenPersistentVolumeSpec(in v1.PersistentVolumeSpec) []interface{} { - att := make(map[string]interface{}) - if len(in.Capacity) > 0 { - att["capacity"] = flattenResourceList(in.Capacity) - } - - att["persistent_volume_source"] = flattenPersistentVolumeSource(in.PersistentVolumeSource) - if len(in.AccessModes) > 0 { - att["access_modes"] = flattenPersistentVolumeAccessModes(in.AccessModes) - } - if in.PersistentVolumeReclaimPolicy != "" { - att["persistent_volume_reclaim_policy"] = in.PersistentVolumeReclaimPolicy - } - if in.StorageClassName != "" { - att["storage_class_name"] = in.StorageClassName - } - return []interface{}{att} -} - -func flattenPhotonPersistentDiskVolumeSource(in *v1.PhotonPersistentDiskVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["pd_id"] = in.PdID - if in.FSType != "" { - att["fs_type"] = in.FSType - } - return []interface{}{att} -} - -func flattenQuobyteVolumeSource(in *v1.QuobyteVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["registry"] = in.Registry - att["volume"] = in.Volume - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - if in.User != "" { - att["user"] = in.User - } - if in.Group != "" { - att["group"] = in.Group - } - return []interface{}{att} -} - -func flattenRBDVolumeSource(in *v1.RBDVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["ceph_monitors"] = newStringSet(schema.HashString, in.CephMonitors) - att["rbd_image"] = in.RBDImage - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.RBDPool != "" { - att["rbd_pool"] = in.RBDPool - } - if in.RadosUser != "" { - att["rados_user"] = in.RadosUser - } - if in.Keyring != "" { - att["keyring"] = in.Keyring - } - if in.SecretRef != nil { - att["secret_ref"] = flattenLocalObjectReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenRBDPersistentVolumeSource(in *v1.RBDPersistentVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["ceph_monitors"] = newStringSet(schema.HashString, in.CephMonitors) - att["rbd_image"] = in.RBDImage - if in.FSType != "" { - att["fs_type"] = in.FSType - } - if in.RBDPool != "" { - att["rbd_pool"] = in.RBDPool - } - if in.RadosUser != "" { - att["rados_user"] = in.RadosUser - } - if in.Keyring != "" { - att["keyring"] = in.Keyring - } - if in.SecretRef != nil { - att["secret_ref"] = flattenSecretReference(in.SecretRef) - } - if in.ReadOnly != false { - att["read_only"] = in.ReadOnly - } - return []interface{}{att} -} - -func flattenVsphereVirtualDiskVolumeSource(in *v1.VsphereVirtualDiskVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["volume_path"] = in.VolumePath - if in.FSType != "" { - att["fs_type"] = in.FSType - } - return []interface{}{att} -} - -// Expanders - -func expandAWSElasticBlockStoreVolumeSource(l []interface{}) *v1.AWSElasticBlockStoreVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.AWSElasticBlockStoreVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.AWSElasticBlockStoreVolumeSource{ - VolumeID: in["volume_id"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["partition"].(int); ok { - obj.Partition = int32(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandAzureDiskVolumeSource(l []interface{}) *v1.AzureDiskVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.AzureDiskVolumeSource{} - } - in := l[0].(map[string]interface{}) - cachingMode := v1.AzureDataDiskCachingMode(in["caching_mode"].(string)) - obj := &v1.AzureDiskVolumeSource{ - CachingMode: &cachingMode, - DiskName: in["disk_name"].(string), - DataDiskURI: in["data_disk_uri"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = ptrToString(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = ptrToBool(v) - } - return obj -} - -func expandAzureFileVolumeSource(l []interface{}) *v1.AzureFileVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.AzureFileVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.AzureFileVolumeSource{ - SecretName: in["secret_name"].(string), - ShareName: in["share_name"].(string), - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandAzureFilePersistentVolumeSource(l []interface{}) *v1.AzureFilePersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.AzureFilePersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.AzureFilePersistentVolumeSource{ - SecretName: in["secret_name"].(string), - ShareName: in["share_name"].(string), - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandCephFSVolumeSource(l []interface{}) *v1.CephFSVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.CephFSVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.CephFSVolumeSource{ - Monitors: sliceOfString(in["monitors"].(*schema.Set).List()), - } - if v, ok := in["path"].(string); ok { - obj.Path = v - } - if v, ok := in["user"].(string); ok { - obj.User = v - } - if v, ok := in["secret_file"].(string); ok { - obj.SecretFile = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandLocalObjectReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandCephFSPersistentVolumeSource(l []interface{}) *v1.CephFSPersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.CephFSPersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.CephFSPersistentVolumeSource{ - Monitors: sliceOfString(in["monitors"].(*schema.Set).List()), - } - if v, ok := in["path"].(string); ok { - obj.Path = v - } - if v, ok := in["user"].(string); ok { - obj.User = v - } - if v, ok := in["secret_file"].(string); ok { - obj.SecretFile = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandSecretReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandCinderVolumeSource(l []interface{}) *v1.CinderVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.CinderVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.CinderVolumeSource{ - VolumeID: in["volume_id"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandFCVolumeSource(l []interface{}) *v1.FCVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.FCVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.FCVolumeSource{ - TargetWWNs: sliceOfString(in["target_ww_ns"].(*schema.Set).List()), - Lun: ptrToInt32(int32(in["lun"].(int))), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandFlexPersistentVolumeSource(l []interface{}) *v1.FlexPersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.FlexPersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.FlexPersistentVolumeSource{ - Driver: in["driver"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandSecretReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - if v, ok := in["options"].(map[string]interface{}); ok && len(v) > 0 { - obj.Options = expandStringMap(v) - } - return obj -} - -func expandFlexVolumeSource(l []interface{}) *v1.FlexVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.FlexVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.FlexVolumeSource{ - Driver: in["driver"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandLocalObjectReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - if v, ok := in["options"].(map[string]interface{}); ok && len(v) > 0 { - obj.Options = expandStringMap(v) - } - return obj -} - -func expandFlockerVolumeSource(l []interface{}) *v1.FlockerVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.FlockerVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.FlockerVolumeSource{ - DatasetName: in["dataset_name"].(string), - DatasetUUID: in["dataset_uuid"].(string), - } - return obj -} - -func expandGCEPersistentDiskVolumeSource(l []interface{}) *v1.GCEPersistentDiskVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.GCEPersistentDiskVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.GCEPersistentDiskVolumeSource{ - PDName: in["pd_name"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["partition"].(int); ok { - obj.Partition = int32(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandGlusterfsVolumeSource(l []interface{}) *v1.GlusterfsVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.GlusterfsVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.GlusterfsVolumeSource{ - EndpointsName: in["endpoints_name"].(string), - Path: in["path"].(string), - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandHostPathVolumeSource(l []interface{}) *v1.HostPathVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.HostPathVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.HostPathVolumeSource{ - Path: in["path"].(string), - } - return obj -} - -func expandISCSIVolumeSource(l []interface{}) *v1.ISCSIVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.ISCSIVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.ISCSIVolumeSource{ - TargetPortal: in["target_portal"].(string), - IQN: in["iqn"].(string), - } - if v, ok := in["lun"].(int); ok { - obj.Lun = int32(v) - } - if v, ok := in["iscsi_interface"].(string); ok { - obj.ISCSIInterface = v - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandISCSIPersistentVolumeSource(l []interface{}) *v1.ISCSIPersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.ISCSIPersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.ISCSIPersistentVolumeSource{ - TargetPortal: in["target_portal"].(string), - IQN: in["iqn"].(string), - } - if v, ok := in["lun"].(int); ok { - obj.Lun = int32(v) - } - if v, ok := in["iscsi_interface"].(string); ok { - obj.ISCSIInterface = v - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandLocalObjectReference(l []interface{}) *v1.LocalObjectReference { - if len(l) == 0 || l[0] == nil { - return &v1.LocalObjectReference{} - } - in := l[0].(map[string]interface{}) - obj := &v1.LocalObjectReference{} - if v, ok := in["name"].(string); ok { - obj.Name = v - } - return obj -} - -func expandSecretReference(l []interface{}) *v1.SecretReference { - if len(l) == 0 || l[0] == nil { - return &v1.SecretReference{} - } - in := l[0].(map[string]interface{}) - obj := &v1.SecretReference{} - if v, ok := in["name"].(string); ok { - obj.Name = v - } - return obj -} - -func expandNFSVolumeSource(l []interface{}) *v1.NFSVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.NFSVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.NFSVolumeSource{ - Server: in["server"].(string), - Path: in["path"].(string), - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandPersistentVolumeSource(l []interface{}) v1.PersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return v1.PersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := v1.PersistentVolumeSource{} - if v, ok := in["gce_persistent_disk"].([]interface{}); ok && len(v) > 0 { - obj.GCEPersistentDisk = expandGCEPersistentDiskVolumeSource(v) - } - if v, ok := in["aws_elastic_block_store"].([]interface{}); ok && len(v) > 0 { - obj.AWSElasticBlockStore = expandAWSElasticBlockStoreVolumeSource(v) - } - if v, ok := in["host_path"].([]interface{}); ok && len(v) > 0 { - obj.HostPath = expandHostPathVolumeSource(v) - } - if v, ok := in["glusterfs"].([]interface{}); ok && len(v) > 0 { - obj.Glusterfs = expandGlusterfsVolumeSource(v) - } - if v, ok := in["nfs"].([]interface{}); ok && len(v) > 0 { - obj.NFS = expandNFSVolumeSource(v) - } - if v, ok := in["rbd"].([]interface{}); ok && len(v) > 0 { - obj.RBD = expandRBDPersistentVolumeSource(v) - } - if v, ok := in["iscsi"].([]interface{}); ok && len(v) > 0 { - obj.ISCSI = expandISCSIPersistentVolumeSource(v) - } - if v, ok := in["cinder"].([]interface{}); ok && len(v) > 0 { - obj.Cinder = expandCinderVolumeSource(v) - } - if v, ok := in["ceph_fs"].([]interface{}); ok && len(v) > 0 { - obj.CephFS = expandCephFSPersistentVolumeSource(v) - } - if v, ok := in["fc"].([]interface{}); ok && len(v) > 0 { - obj.FC = expandFCVolumeSource(v) - } - if v, ok := in["flocker"].([]interface{}); ok && len(v) > 0 { - obj.Flocker = expandFlockerVolumeSource(v) - } - if v, ok := in["flex_volume"].([]interface{}); ok && len(v) > 0 { - obj.FlexVolume = expandFlexPersistentVolumeSource(v) - } - if v, ok := in["azure_file"].([]interface{}); ok && len(v) > 0 { - obj.AzureFile = expandAzureFilePersistentVolumeSource(v) - } - if v, ok := in["vsphere_volume"].([]interface{}); ok && len(v) > 0 { - obj.VsphereVolume = expandVsphereVirtualDiskVolumeSource(v) - } - if v, ok := in["quobyte"].([]interface{}); ok && len(v) > 0 { - obj.Quobyte = expandQuobyteVolumeSource(v) - } - if v, ok := in["azure_disk"].([]interface{}); ok && len(v) > 0 { - obj.AzureDisk = expandAzureDiskVolumeSource(v) - } - if v, ok := in["photon_persistent_disk"].([]interface{}); ok && len(v) > 0 { - obj.PhotonPersistentDisk = expandPhotonPersistentDiskVolumeSource(v) - } - return obj -} - -func expandPersistentVolumeSpec(l []interface{}) (v1.PersistentVolumeSpec, error) { - if len(l) == 0 || l[0] == nil { - return v1.PersistentVolumeSpec{}, nil - } - in := l[0].(map[string]interface{}) - obj := v1.PersistentVolumeSpec{} - if v, ok := in["capacity"].(map[string]interface{}); ok && len(v) > 0 { - var err error - obj.Capacity, err = expandMapToResourceList(v) - if err != nil { - return obj, err - } - } - if v, ok := in["persistent_volume_source"].([]interface{}); ok && len(v) > 0 { - obj.PersistentVolumeSource = expandPersistentVolumeSource(v) - } - if v, ok := in["access_modes"].(*schema.Set); ok && v.Len() > 0 { - obj.AccessModes = expandPersistentVolumeAccessModes(v.List()) - } - if v, ok := in["persistent_volume_reclaim_policy"].(string); ok { - obj.PersistentVolumeReclaimPolicy = v1.PersistentVolumeReclaimPolicy(v) - } - if v, ok := in["storage_class_name"].(string); ok { - obj.StorageClassName = v - } - return obj, nil -} - -func expandPhotonPersistentDiskVolumeSource(l []interface{}) *v1.PhotonPersistentDiskVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.PhotonPersistentDiskVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.PhotonPersistentDiskVolumeSource{ - PdID: in["pd_id"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - return obj -} - -func expandQuobyteVolumeSource(l []interface{}) *v1.QuobyteVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.QuobyteVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.QuobyteVolumeSource{ - Registry: in["registry"].(string), - Volume: in["volume"].(string), - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - if v, ok := in["user"].(string); ok { - obj.User = v - } - if v, ok := in["group"].(string); ok { - obj.Group = v - } - return obj -} - -func expandRBDVolumeSource(l []interface{}) *v1.RBDVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.RBDVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.RBDVolumeSource{ - CephMonitors: expandStringSlice(in["ceph_monitors"].(*schema.Set).List()), - RBDImage: in["rbd_image"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["rbd_pool"].(string); ok { - obj.RBDPool = v - } - if v, ok := in["rados_user"].(string); ok { - obj.RadosUser = v - } - if v, ok := in["keyring"].(string); ok { - obj.Keyring = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandLocalObjectReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandRBDPersistentVolumeSource(l []interface{}) *v1.RBDPersistentVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.RBDPersistentVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.RBDPersistentVolumeSource{ - CephMonitors: expandStringSlice(in["ceph_monitors"].(*schema.Set).List()), - RBDImage: in["rbd_image"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - if v, ok := in["rbd_pool"].(string); ok { - obj.RBDPool = v - } - if v, ok := in["rados_user"].(string); ok { - obj.RadosUser = v - } - if v, ok := in["keyring"].(string); ok { - obj.Keyring = v - } - if v, ok := in["secret_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretRef = expandSecretReference(v) - } - if v, ok := in["read_only"].(bool); ok { - obj.ReadOnly = v - } - return obj -} - -func expandVsphereVirtualDiskVolumeSource(l []interface{}) *v1.VsphereVirtualDiskVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.VsphereVirtualDiskVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.VsphereVirtualDiskVolumeSource{ - VolumePath: in["volume_path"].(string), - } - if v, ok := in["fs_type"].(string); ok { - obj.FSType = v - } - return obj -} - -func patchPersistentVolumeSpec(pathPrefix, prefix string, d *schema.ResourceData) (PatchOperations, error) { - ops := make([]PatchOperation, 0) - prefix += ".0." - - if d.HasChange(prefix + "capacity") { - v := d.Get(prefix + "capacity").(map[string]interface{}) - capacity, err := expandMapToResourceList(v) - if err != nil { - return ops, err - } - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/capacity", - Value: capacity, - }) - } - - if d.HasChange(prefix + "persistent_volume_source") { - ops = append(ops, patchPersistentVolumeSource( - pathPrefix, - prefix+"persistent_volume_source.0.", - d, - )...) - } - - if d.HasChange(prefix + "access_modes") { - v := d.Get(prefix + "access_modes").(*schema.Set) - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/accessModes", - Value: expandPersistentVolumeAccessModes(v.List()), - }) - } - if d.HasChange(prefix + "persistent_volume_reclaim_policy") { - v := d.Get(prefix + "persistent_volume_reclaim_policy").(string) - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/persistentVolumeReclaimPolicy", - Value: v1.PersistentVolumeReclaimPolicy(v), - }) - } - if d.HasChange(prefix + "storage_class_name") { - o, n := d.GetChange(prefix + "storage_class_name") - if v, ok := o.(string); ok && len(v) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/storageClassName", - Value: n.(string), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/storageClassName", - Value: n.(string), - }) - } - } - - return ops, nil -} - -func patchPersistentVolumeSource(pathPrefix, prefix string, d *schema.ResourceData) []PatchOperation { - ops := make([]PatchOperation, 0) - - if d.HasChange(prefix + "gce_persistent_disk") { - oldIn, newIn := d.GetChange(prefix + "gce_persistent_disk") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/gcePersistentDisk", - Value: expandGCEPersistentDiskVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/gcePersistentDisk", - Value: expandGCEPersistentDiskVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/gcePersistentDisk"}) - } - } - - if d.HasChange(prefix + "aws_elastic_block_store") { - oldIn, newIn := d.GetChange(prefix + "aws_elastic_block_store") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/awsElasticBlockStore", - Value: expandAWSElasticBlockStoreVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/awsElasticBlockStore", - Value: expandAWSElasticBlockStoreVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/awsElasticBlockStore"}) - } - } - - if d.HasChange(prefix + "host_path") { - oldIn, newIn := d.GetChange(prefix + "host_path") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/hostPath", - Value: expandHostPathVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/hostPath", - Value: expandHostPathVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/hostPath"}) - } - } - - if d.HasChange(prefix + "glusterfs") { - oldIn, newIn := d.GetChange(prefix + "glusterfs") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/glusterfs", - Value: expandGlusterfsVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/glusterfs", - Value: expandGlusterfsVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/glusterfs"}) - } - } - - if d.HasChange(prefix + "nfs") { - oldIn, newIn := d.GetChange(prefix + "nfs") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/nfs", - Value: expandNFSVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/nfs", - Value: expandNFSVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/nfs"}) - } - } - - if d.HasChange(prefix + "rbd") { - oldIn, newIn := d.GetChange(prefix + "rbd") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/rbd", - Value: expandRBDVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/rbd", - Value: expandRBDVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/rbd"}) - } - } - - if d.HasChange(prefix + "iscsi") { - oldIn, newIn := d.GetChange(prefix + "iscsi") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/iscsi", - Value: expandISCSIVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/iscsi", - Value: expandISCSIVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/iscsi"}) - } - } - - if d.HasChange(prefix + "cinder") { - oldIn, newIn := d.GetChange(prefix + "cinder") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/cinder", - Value: expandCinderVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/cinder", - Value: expandCinderVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/cinder"}) - } - } - - if d.HasChange(prefix + "ceph_fs") { - oldIn, newIn := d.GetChange(prefix + "ceph_fs") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/cephfs", - Value: expandCephFSVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/cephfs", - Value: expandCephFSVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/cephfs"}) - } - } - - if d.HasChange(prefix + "fc") { - oldIn, newIn := d.GetChange(prefix + "fc") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/fc", - Value: expandFCVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/fc", - Value: expandFCVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/fc"}) - } - } - - if d.HasChange(prefix + "flocker") { - oldIn, newIn := d.GetChange(prefix + "flocker") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/flocker", - Value: expandFlockerVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/flocker", - Value: expandFlockerVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/flocker"}) - } - } - - if d.HasChange(prefix + "flex_volume") { - oldIn, newIn := d.GetChange(prefix + "flex_volume") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/flexVolume", - Value: expandFlexVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/flexVolume", - Value: expandFlexVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/flexVolume"}) - } - } - - if d.HasChange(prefix + "azure_file") { - oldIn, newIn := d.GetChange(prefix + "azure_file") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/azureFile", - Value: expandAzureFileVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/azureFile", - Value: expandAzureFileVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/azureFile"}) - } - } - - if d.HasChange(prefix + "vsphere_volume") { - oldIn, newIn := d.GetChange(prefix + "vsphere_volume") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/vsphereVolume", - Value: expandVsphereVirtualDiskVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/vsphereVolume", - Value: expandVsphereVirtualDiskVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/vsphereVolume"}) - } - } - - if d.HasChange(prefix + "quobyte") { - oldIn, newIn := d.GetChange(prefix + "quobyte") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/quobyte", - Value: expandQuobyteVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/quobyte", - Value: expandQuobyteVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/quobyte"}) - } - } - - if d.HasChange(prefix + "azure_disk") { - oldIn, newIn := d.GetChange(prefix + "azure_disk") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/azureDisk", - Value: expandAzureDiskVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/azureDisk", - Value: expandAzureDiskVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/azureDisk"}) - } - } - - if d.HasChange(prefix + "photon_persistent_disk") { - oldIn, newIn := d.GetChange(prefix + "photon_persistent_disk") - oldV, oldOk := oldIn.([]interface{}) - newV, newOk := newIn.([]interface{}) - - if newOk && len(newV) > 0 { - if oldOk && len(oldV) > 0 { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/photonPersistentDisk", - Value: expandPhotonPersistentDiskVolumeSource(newV), - }) - } else { - ops = append(ops, &AddOperation{ - Path: pathPrefix + "/photonPersistentDisk", - Value: expandPhotonPersistentDiskVolumeSource(newV), - }) - } - } else if oldOk && len(oldV) > 0 { - ops = append(ops, &RemoveOperation{Path: pathPrefix + "/photonPersistentDisk"}) - } - } - - return ops -} diff --git a/kubernetes/structure_service_spec.go b/kubernetes/structure_service_spec.go deleted file mode 100644 index 7d3078b2ba..0000000000 --- a/kubernetes/structure_service_spec.go +++ /dev/null @@ -1,202 +0,0 @@ -package kubernetes - -import ( - gversion "github.com/hashicorp/go-version" - "github.com/hashicorp/terraform/helper/schema" - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/version" -) - -// Flatteners - -func flattenServicePort(in []v1.ServicePort) []interface{} { - att := make([]interface{}, len(in), len(in)) - for i, n := range in { - m := make(map[string]interface{}) - m["name"] = n.Name - m["protocol"] = string(n.Protocol) - m["port"] = int(n.Port) - m["target_port"] = n.TargetPort.String() - m["node_port"] = int(n.NodePort) - - att[i] = m - } - return att -} - -func flattenServiceSpec(in v1.ServiceSpec) []interface{} { - att := make(map[string]interface{}) - if len(in.Ports) > 0 { - att["port"] = flattenServicePort(in.Ports) - } - if len(in.Selector) > 0 { - att["selector"] = in.Selector - } - if in.ClusterIP != "" { - att["cluster_ip"] = in.ClusterIP - } - if in.Type != "" { - att["type"] = string(in.Type) - } - if len(in.ExternalIPs) > 0 { - att["external_ips"] = newStringSet(schema.HashString, in.ExternalIPs) - } - if in.SessionAffinity != "" { - att["session_affinity"] = string(in.SessionAffinity) - } - if in.LoadBalancerIP != "" { - att["load_balancer_ip"] = in.LoadBalancerIP - } - if len(in.LoadBalancerSourceRanges) > 0 { - att["load_balancer_source_ranges"] = newStringSet(schema.HashString, in.LoadBalancerSourceRanges) - } - if in.ExternalName != "" { - att["external_name"] = in.ExternalName - } - return []interface{}{att} -} - -func flattenLoadBalancerIngress(in []v1.LoadBalancerIngress) []interface{} { - out := make([]interface{}, len(in), len(in)) - for i, ingress := range in { - att := make(map[string]interface{}) - - att["ip"] = ingress.IP - att["hostname"] = ingress.Hostname - - out[i] = att - } - return out -} - -// Expanders - -func expandServicePort(l []interface{}) []v1.ServicePort { - if len(l) == 0 || l[0] == nil { - return []v1.ServicePort{} - } - obj := make([]v1.ServicePort, len(l), len(l)) - for i, n := range l { - cfg := n.(map[string]interface{}) - obj[i] = v1.ServicePort{ - Port: int32(cfg["port"].(int)), - TargetPort: intstr.Parse(cfg["target_port"].(string)), - } - if v, ok := cfg["name"].(string); ok { - obj[i].Name = v - } - if v, ok := cfg["protocol"].(string); ok { - obj[i].Protocol = v1.Protocol(v) - } - if v, ok := cfg["node_port"].(int); ok { - obj[i].NodePort = int32(v) - } - } - return obj -} - -func expandServiceSpec(l []interface{}) v1.ServiceSpec { - if len(l) == 0 || l[0] == nil { - return v1.ServiceSpec{} - } - in := l[0].(map[string]interface{}) - obj := v1.ServiceSpec{} - - if v, ok := in["port"].([]interface{}); ok && len(v) > 0 { - obj.Ports = expandServicePort(v) - } - if v, ok := in["selector"].(map[string]interface{}); ok && len(v) > 0 { - obj.Selector = expandStringMap(v) - } - if v, ok := in["cluster_ip"].(string); ok { - obj.ClusterIP = v - } - if v, ok := in["type"].(string); ok { - obj.Type = v1.ServiceType(v) - } - if v, ok := in["external_ips"].(*schema.Set); ok && v.Len() > 0 { - obj.ExternalIPs = sliceOfString(v.List()) - } - if v, ok := in["session_affinity"].(string); ok { - obj.SessionAffinity = v1.ServiceAffinity(v) - } - if v, ok := in["load_balancer_ip"].(string); ok { - obj.LoadBalancerIP = v - } - if v, ok := in["load_balancer_source_ranges"].(*schema.Set); ok && v.Len() > 0 { - obj.LoadBalancerSourceRanges = sliceOfString(v.List()) - } - if v, ok := in["external_name"].(string); ok { - obj.ExternalName = v - } - return obj -} - -// Patch Ops - -func patchServiceSpec(keyPrefix, pathPrefix string, d *schema.ResourceData, v *version.Info) (PatchOperations, error) { - ops := make([]PatchOperation, 0, 0) - if d.HasChange(keyPrefix + "selector") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "selector", - Value: d.Get(keyPrefix + "selector").(map[string]interface{}), - }) - } - if d.HasChange(keyPrefix + "type") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "type", - Value: d.Get(keyPrefix + "type").(string), - }) - } - if d.HasChange(keyPrefix + "session_affinity") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "sessionAffinity", - Value: d.Get(keyPrefix + "session_affinity").(string), - }) - } - if d.HasChange(keyPrefix + "load_balancer_ip") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "loadBalancerIP", - Value: d.Get(keyPrefix + "load_balancer_ip").(string), - }) - } - if d.HasChange(keyPrefix + "load_balancer_source_ranges") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "loadBalancerSourceRanges", - Value: d.Get(keyPrefix + "load_balancer_source_ranges").(*schema.Set).List(), - }) - } - if d.HasChange(keyPrefix + "port") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "ports", - Value: expandServicePort(d.Get(keyPrefix + "port").([]interface{})), - }) - } - if d.HasChange(keyPrefix + "external_ips") { - k8sVersion, err := gversion.NewVersion(v.String()) - if err != nil { - return nil, err - } - v1_8_0, _ := gversion.NewVersion("1.8.0") - if k8sVersion.LessThan(v1_8_0) { - // If we haven't done this the deprecated field would have priority - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "deprecatedPublicIPs", - Value: nil, - }) - } - - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "externalIPs", - Value: d.Get(keyPrefix + "external_ips").(*schema.Set).List(), - }) - } - if d.HasChange(keyPrefix + "external_name") { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "externalName", - Value: d.Get(keyPrefix + "external_name").(string), - }) - } - return ops, nil -} diff --git a/kubernetes/structures_container.go b/kubernetes/structures_container.go deleted file mode 100644 index c8ba672182..0000000000 --- a/kubernetes/structures_container.go +++ /dev/null @@ -1,962 +0,0 @@ -package kubernetes - -import ( - "strconv" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func flattenCapability(in []v1.Capability) []string { - att := make([]string, len(in), len(in)) - for i, v := range in { - att[i] = string(v) - } - return att -} - -func flattenContainerSecurityContext(in *v1.SecurityContext) []interface{} { - att := make(map[string]interface{}) - - if in.Privileged != nil { - att["privileged"] = *in.Privileged - } - if in.ReadOnlyRootFilesystem != nil { - att["read_only_root_filesystem"] = *in.ReadOnlyRootFilesystem - } - - if in.RunAsNonRoot != nil { - att["run_as_non_root"] = *in.RunAsNonRoot - } - if in.RunAsUser != nil { - att["run_as_user"] = *in.RunAsUser - } - - if in.SELinuxOptions != nil { - att["se_linux_options"] = flattenSeLinuxOptions(in.SELinuxOptions) - } - if in.Capabilities != nil { - att["capabilities"] = flattenSecurityCapabilities(in.Capabilities) - } - return []interface{}{att} - -} - -func flattenSecurityCapabilities(in *v1.Capabilities) []interface{} { - att := make(map[string]interface{}) - - if in.Add != nil { - att["add"] = flattenCapability(in.Add) - } - if in.Drop != nil { - att["drop"] = flattenCapability(in.Drop) - } - - return []interface{}{att} -} - -func flattenHandler(in *v1.Handler) []interface{} { - att := make(map[string]interface{}) - - if in.Exec != nil { - att["exec"] = flattenExec(in.Exec) - } - if in.HTTPGet != nil { - att["http_get"] = flattenHTTPGet(in.HTTPGet) - } - if in.TCPSocket != nil { - att["tcp_socket"] = flattenTCPSocket(in.TCPSocket) - } - - return []interface{}{att} -} - -func flattenHTTPHeader(in []v1.HTTPHeader) []interface{} { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - - if v.Name != "" { - m["name"] = v.Name - } - - if v.Value != "" { - m["value"] = v.Value - } - att[i] = m - } - return att -} - -func expandPort(v string) intstr.IntOrString { - i, err := strconv.Atoi(v) - if err != nil { - return intstr.IntOrString{ - Type: intstr.String, - StrVal: v, - } - } - return intstr.IntOrString{ - Type: intstr.Int, - IntVal: int32(i), - } -} - -func flattenHTTPGet(in *v1.HTTPGetAction) []interface{} { - att := make(map[string]interface{}) - - if in.Host != "" { - att["host"] = in.Host - } - if in.Path != "" { - att["path"] = in.Path - } - att["port"] = in.Port.String() - att["scheme"] = in.Scheme - if len(in.HTTPHeaders) > 0 { - att["http_header"] = flattenHTTPHeader(in.HTTPHeaders) - } - - return []interface{}{att} -} - -func flattenTCPSocket(in *v1.TCPSocketAction) []interface{} { - att := make(map[string]interface{}) - att["port"] = in.Port.String() - return []interface{}{att} -} - -func flattenExec(in *v1.ExecAction) []interface{} { - att := make(map[string]interface{}) - if len(in.Command) > 0 { - att["command"] = in.Command - } - return []interface{}{att} -} - -func flattenLifeCycle(in *v1.Lifecycle) []interface{} { - att := make(map[string]interface{}) - - if in.PostStart != nil { - att["post_start"] = flattenHandler(in.PostStart) - } - if in.PreStop != nil { - att["pre_stop"] = flattenHandler(in.PreStop) - } - - return []interface{}{att} -} - -func flattenProbe(in *v1.Probe) []interface{} { - att := make(map[string]interface{}) - - att["failure_threshold"] = in.FailureThreshold - att["initial_delay_seconds"] = in.InitialDelaySeconds - att["period_seconds"] = in.PeriodSeconds - att["success_threshold"] = in.SuccessThreshold - att["timeout_seconds"] = in.TimeoutSeconds - - if in.Exec != nil { - att["exec"] = flattenExec(in.Exec) - } - if in.HTTPGet != nil { - att["http_get"] = flattenHTTPGet(in.HTTPGet) - } - if in.TCPSocket != nil { - att["tcp_socket"] = flattenTCPSocket(in.TCPSocket) - } - - return []interface{}{att} -} - -func flattenConfigMapRef(in *v1.ConfigMapEnvSource) []interface{} { - att := make(map[string]interface{}) - - if in.Name != "" { - att["name"] = in.Name - } - if in.Optional != nil { - att["optional"] = *in.Optional - } - return []interface{}{att} -} - -func flattenConfigMapKeyRef(in *v1.ConfigMapKeySelector) []interface{} { - att := make(map[string]interface{}) - - if in.Key != "" { - att["key"] = in.Key - } - if in.Name != "" { - att["name"] = in.Name - } - return []interface{}{att} -} - -func flattenObjectFieldSelector(in *v1.ObjectFieldSelector) []interface{} { - att := make(map[string]interface{}) - - if in.APIVersion != "" { - att["api_version"] = in.APIVersion - } - if in.FieldPath != "" { - att["field_path"] = in.FieldPath - } - return []interface{}{att} -} - -func flattenResourceFieldSelector(in *v1.ResourceFieldSelector) []interface{} { - att := make(map[string]interface{}) - - if in.ContainerName != "" { - att["container_name"] = in.ContainerName - } - if in.Resource != "" { - att["resource"] = in.Resource - } - return []interface{}{att} -} - -func flattenSecretRef(in *v1.SecretEnvSource) []interface{} { - att := make(map[string]interface{}) - - if in.Name != "" { - att["name"] = in.Name - } - if in.Optional != nil { - att["optional"] = *in.Optional - } - return []interface{}{att} -} - -func flattenSecretKeyRef(in *v1.SecretKeySelector) []interface{} { - att := make(map[string]interface{}) - - if in.Key != "" { - att["key"] = in.Key - } - if in.Name != "" { - att["name"] = in.Name - } - return []interface{}{att} -} - -func flattenValueFrom(in *v1.EnvVarSource) []interface{} { - att := make(map[string]interface{}) - - if in.ConfigMapKeyRef != nil { - att["config_map_key_ref"] = flattenConfigMapKeyRef(in.ConfigMapKeyRef) - } - if in.ResourceFieldRef != nil { - att["resource_field_ref"] = flattenResourceFieldSelector(in.ResourceFieldRef) - } - if in.SecretKeyRef != nil { - att["secret_key_ref"] = flattenSecretKeyRef(in.SecretKeyRef) - } - if in.FieldRef != nil { - att["field_ref"] = flattenObjectFieldSelector(in.FieldRef) - } - return []interface{}{att} -} - -func flattenContainerVolumeMounts(in []v1.VolumeMount) ([]interface{}, error) { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - m["read_only"] = v.ReadOnly - - if v.MountPath != "" { - m["mount_path"] = v.MountPath - - } - if v.Name != "" { - m["name"] = v.Name - - } - if v.SubPath != "" { - m["sub_path"] = v.SubPath - } - att[i] = m - } - return att, nil -} - -func flattenContainerEnvs(in []v1.EnvVar) []interface{} { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - if v.Name != "" { - m["name"] = v.Name - } - if v.Value != "" { - m["value"] = v.Value - } - if v.ValueFrom != nil { - m["value_from"] = flattenValueFrom(v.ValueFrom) - } - - att[i] = m - } - return att -} - -func flattenContainerEnvFroms(in []v1.EnvFromSource) []interface{} { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - if v.ConfigMapRef != nil { - m["config_map_ref"] = flattenConfigMapRef(v.ConfigMapRef) - } - if v.Prefix != "" { - m["prefix"] = v.Prefix - } - if v.SecretRef != nil { - m["secret_ref"] = flattenSecretRef(v.SecretRef) - } - - att[i] = m - } - return att -} - -func flattenContainerPorts(in []v1.ContainerPort) []interface{} { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - m["container_port"] = v.ContainerPort - if v.HostIP != "" { - m["host_ip"] = v.HostIP - } - m["host_port"] = v.HostPort - if v.Name != "" { - m["name"] = v.Name - } - if v.Protocol != "" { - m["protocol"] = v.Protocol - } - att[i] = m - } - return att -} - -func flattenContainerResourceRequirements(in v1.ResourceRequirements) ([]interface{}, error) { - att := make(map[string]interface{}) - if len(in.Limits) > 0 { - att["limits"] = []interface{}{flattenResourceList(in.Limits)} - } - if len(in.Requests) > 0 { - att["requests"] = []interface{}{flattenResourceList(in.Requests)} - } - return []interface{}{att}, nil -} - -func flattenContainers(in []v1.Container) ([]interface{}, error) { - att := make([]interface{}, len(in)) - for i, v := range in { - c := make(map[string]interface{}) - c["image"] = v.Image - c["name"] = v.Name - if len(v.Command) > 0 { - c["command"] = v.Command - } - if len(v.Args) > 0 { - c["args"] = v.Args - } - - c["image_pull_policy"] = v.ImagePullPolicy - c["termination_message_path"] = v.TerminationMessagePath - c["stdin"] = v.Stdin - c["stdin_once"] = v.StdinOnce - c["tty"] = v.TTY - c["working_dir"] = v.WorkingDir - res, err := flattenContainerResourceRequirements(v.Resources) - if err != nil { - return nil, err - } - - c["resources"] = res - if v.LivenessProbe != nil { - c["liveness_probe"] = flattenProbe(v.LivenessProbe) - } - if v.ReadinessProbe != nil { - c["readiness_probe"] = flattenProbe(v.ReadinessProbe) - } - if v.Lifecycle != nil { - c["lifecycle"] = flattenLifeCycle(v.Lifecycle) - } - - if v.SecurityContext != nil { - c["security_context"] = flattenContainerSecurityContext(v.SecurityContext) - } - if len(v.Ports) > 0 { - c["port"] = flattenContainerPorts(v.Ports) - } - if len(v.Env) > 0 { - c["env"] = flattenContainerEnvs(v.Env) - } - if len(v.EnvFrom) > 0 { - c["env_from"] = flattenContainerEnvFroms(v.EnvFrom) - } - - if len(v.VolumeMounts) > 0 { - volumeMounts, err := flattenContainerVolumeMounts(v.VolumeMounts) - if err != nil { - return nil, err - } - c["volume_mount"] = volumeMounts - } - att[i] = c - } - return att, nil -} - -func expandContainers(ctrs []interface{}) ([]v1.Container, error) { - if len(ctrs) == 0 { - return []v1.Container{}, nil - } - cs := make([]v1.Container, len(ctrs)) - for i, c := range ctrs { - ctr := c.(map[string]interface{}) - - if image, ok := ctr["image"]; ok { - cs[i].Image = image.(string) - } - if name, ok := ctr["name"]; ok { - cs[i].Name = name.(string) - } - if command, ok := ctr["command"].([]interface{}); ok { - cs[i].Command = expandStringSlice(command) - } - if args, ok := ctr["args"].([]interface{}); ok { - cs[i].Args = expandStringSlice(args) - } - - if v, ok := ctr["resources"].([]interface{}); ok && len(v) > 0 { - - var err error - cs[i].Resources, err = expandContainerResourceRequirements(v) - if err != nil { - return cs, err - } - } - - if v, ok := ctr["port"].([]interface{}); ok && len(v) > 0 { - var err error - cs[i].Ports, err = expandContainerPort(v) - if err != nil { - return cs, err - } - } - if v, ok := ctr["env"].([]interface{}); ok && len(v) > 0 { - var err error - cs[i].Env, err = expandContainerEnv(v) - if err != nil { - return cs, err - } - } - if v, ok := ctr["env_from"].([]interface{}); ok && len(v) > 0 { - var err error - cs[i].EnvFrom, err = expandContainerEnvFrom(v) - if err != nil { - return cs, err - } - } - - if policy, ok := ctr["image_pull_policy"]; ok { - cs[i].ImagePullPolicy = v1.PullPolicy(policy.(string)) - } - - if v, ok := ctr["lifecycle"].([]interface{}); ok && len(v) > 0 { - cs[i].Lifecycle = expandLifeCycle(v) - } - - if v, ok := ctr["liveness_probe"].([]interface{}); ok && len(v) > 0 { - cs[i].LivenessProbe = expandProbe(v) - } - - if v, ok := ctr["readiness_probe"].([]interface{}); ok && len(v) > 0 { - cs[i].ReadinessProbe = expandProbe(v) - } - if v, ok := ctr["stdin"]; ok { - cs[i].Stdin = v.(bool) - } - if v, ok := ctr["stdin_once"]; ok { - cs[i].StdinOnce = v.(bool) - } - if v, ok := ctr["termination_message_path"]; ok { - cs[i].TerminationMessagePath = v.(string) - } - if v, ok := ctr["tty"]; ok { - cs[i].TTY = v.(bool) - } - if v, ok := ctr["security_context"].([]interface{}); ok && len(v) > 0 { - cs[i].SecurityContext = expandContainerSecurityContext(v) - } - - if v, ok := ctr["volume_mount"].([]interface{}); ok && len(v) > 0 { - var err error - cs[i].VolumeMounts, err = expandContainerVolumeMounts(v) - if err != nil { - return cs, err - } - } - } - return cs, nil -} - -func expandExec(l []interface{}) *v1.ExecAction { - if len(l) == 0 || l[0] == nil { - return &v1.ExecAction{} - } - in := l[0].(map[string]interface{}) - obj := v1.ExecAction{} - if v, ok := in["command"].([]interface{}); ok && len(v) > 0 { - obj.Command = expandStringSlice(v) - } - return &obj -} - -func expandHTTPHeaders(l []interface{}) []v1.HTTPHeader { - if len(l) == 0 { - return []v1.HTTPHeader{} - } - headers := make([]v1.HTTPHeader, len(l)) - for i, c := range l { - m := c.(map[string]interface{}) - if v, ok := m["name"]; ok { - headers[i].Name = v.(string) - } - if v, ok := m["value"]; ok { - headers[i].Value = v.(string) - } - } - return headers -} -func expandContainerSecurityContext(l []interface{}) *v1.SecurityContext { - if len(l) == 0 || l[0] == nil { - return &v1.SecurityContext{} - } - in := l[0].(map[string]interface{}) - obj := v1.SecurityContext{} - if v, ok := in["privileged"]; ok { - obj.Privileged = ptrToBool(v.(bool)) - } - if v, ok := in["read_only_root_filesystem"]; ok { - obj.ReadOnlyRootFilesystem = ptrToBool(v.(bool)) - } - if v, ok := in["run_as_non_root"]; ok { - obj.RunAsNonRoot = ptrToBool(v.(bool)) - } - if v, ok := in["run_as_user"]; ok { - obj.RunAsUser = ptrToInt64(int64(v.(int))) - } - if v, ok := in["se_linux_options"].([]interface{}); ok && len(v) > 0 { - obj.SELinuxOptions = expandSeLinuxOptions(v) - } - if v, ok := in["capabilities"].([]interface{}); ok && len(v) > 0 { - obj.Capabilities = expandSecurityCapabilities(v) - } - - return &obj -} - -func expandCapabilitySlice(s []interface{}) []v1.Capability { - result := make([]v1.Capability, len(s), len(s)) - for k, v := range s { - result[k] = v1.Capability(v.(string)) - } - return result -} - -func expandSecurityCapabilities(l []interface{}) *v1.Capabilities { - if len(l) == 0 || l[0] == nil { - return &v1.Capabilities{} - } - in := l[0].(map[string]interface{}) - obj := v1.Capabilities{} - if v, ok := in["add"].([]interface{}); ok { - obj.Add = expandCapabilitySlice(v) - } - if v, ok := in["drop"].([]interface{}); ok { - obj.Drop = expandCapabilitySlice(v) - } - return &obj -} - -func expandTCPSocket(l []interface{}) *v1.TCPSocketAction { - if len(l) == 0 || l[0] == nil { - return &v1.TCPSocketAction{} - } - in := l[0].(map[string]interface{}) - obj := v1.TCPSocketAction{} - if v, ok := in["port"].(string); ok && len(v) > 0 { - obj.Port = expandPort(v) - } - return &obj -} - -func expandHTTPGet(l []interface{}) *v1.HTTPGetAction { - if len(l) == 0 || l[0] == nil { - return &v1.HTTPGetAction{} - } - in := l[0].(map[string]interface{}) - obj := v1.HTTPGetAction{} - if v, ok := in["host"].(string); ok && len(v) > 0 { - obj.Host = v - } - if v, ok := in["path"].(string); ok && len(v) > 0 { - obj.Path = v - } - if v, ok := in["scheme"].(string); ok && len(v) > 0 { - obj.Scheme = v1.URIScheme(v) - } - - if v, ok := in["port"].(string); ok && len(v) > 0 { - obj.Port = expandPort(v) - } - - if v, ok := in["http_header"].([]interface{}); ok && len(v) > 0 { - obj.HTTPHeaders = expandHTTPHeaders(v) - } - return &obj -} - -func expandProbe(l []interface{}) *v1.Probe { - if len(l) == 0 || l[0] == nil { - return &v1.Probe{} - } - in := l[0].(map[string]interface{}) - obj := v1.Probe{} - if v, ok := in["exec"].([]interface{}); ok && len(v) > 0 { - obj.Exec = expandExec(v) - } - if v, ok := in["http_get"].([]interface{}); ok && len(v) > 0 { - obj.HTTPGet = expandHTTPGet(v) - } - if v, ok := in["tcp_socket"].([]interface{}); ok && len(v) > 0 { - obj.TCPSocket = expandTCPSocket(v) - } - if v, ok := in["failure_threshold"].(int); ok { - obj.FailureThreshold = int32(v) - } - if v, ok := in["initial_delay_seconds"].(int); ok { - obj.InitialDelaySeconds = int32(v) - } - if v, ok := in["period_seconds"].(int); ok { - obj.PeriodSeconds = int32(v) - } - if v, ok := in["success_threshold"].(int); ok { - obj.SuccessThreshold = int32(v) - } - if v, ok := in["timeout_seconds"].(int); ok { - obj.TimeoutSeconds = int32(v) - } - - return &obj -} - -func expandHandlers(l []interface{}) *v1.Handler { - if len(l) == 0 || l[0] == nil { - return &v1.Handler{} - } - in := l[0].(map[string]interface{}) - obj := v1.Handler{} - if v, ok := in["exec"].([]interface{}); ok && len(v) > 0 { - obj.Exec = expandExec(v) - } - if v, ok := in["http_get"].([]interface{}); ok && len(v) > 0 { - obj.HTTPGet = expandHTTPGet(v) - } - if v, ok := in["tcp_socket"].([]interface{}); ok && len(v) > 0 { - obj.TCPSocket = expandTCPSocket(v) - } - return &obj - -} -func expandLifeCycle(l []interface{}) *v1.Lifecycle { - if len(l) == 0 || l[0] == nil { - return &v1.Lifecycle{} - } - in := l[0].(map[string]interface{}) - obj := &v1.Lifecycle{} - if v, ok := in["post_start"].([]interface{}); ok && len(v) > 0 { - obj.PostStart = expandHandlers(v) - } - if v, ok := in["pre_stop"].([]interface{}); ok && len(v) > 0 { - obj.PreStop = expandHandlers(v) - } - return obj -} - -func expandContainerVolumeMounts(in []interface{}) ([]v1.VolumeMount, error) { - if len(in) == 0 { - return []v1.VolumeMount{}, nil - } - vmp := make([]v1.VolumeMount, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if mountPath, ok := p["mount_path"]; ok { - vmp[i].MountPath = mountPath.(string) - } - if name, ok := p["name"]; ok { - vmp[i].Name = name.(string) - } - if readOnly, ok := p["read_only"]; ok { - vmp[i].ReadOnly = readOnly.(bool) - } - if subPath, ok := p["sub_path"]; ok { - vmp[i].SubPath = subPath.(string) - } - } - return vmp, nil -} - -func expandContainerEnv(in []interface{}) ([]v1.EnvVar, error) { - if len(in) == 0 { - return []v1.EnvVar{}, nil - } - envs := make([]v1.EnvVar, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if name, ok := p["name"]; ok { - envs[i].Name = name.(string) - } - if value, ok := p["value"]; ok { - envs[i].Value = value.(string) - } - if v, ok := p["value_from"].([]interface{}); ok && len(v) > 0 { - var err error - envs[i].ValueFrom, err = expandEnvValueFrom(v) - if err != nil { - return envs, err - } - } - } - return envs, nil -} - -func expandContainerEnvFrom(in []interface{}) ([]v1.EnvFromSource, error) { - if len(in) == 0 { - return []v1.EnvFromSource{}, nil - } - envFroms := make([]v1.EnvFromSource, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if v, ok := p["config_map_ref"].([]interface{}); ok && len(v) > 0 { - var err error - envFroms[i].ConfigMapRef, err = expandConfigMapRef(v) - if err != nil { - return envFroms, err - } - } - if value, ok := p["prefix"]; ok { - envFroms[i].Prefix = value.(string) - } - if v, ok := p["secret_ref"].([]interface{}); ok && len(v) > 0 { - var err error - envFroms[i].SecretRef, err = expandSecretRef(v) - if err != nil { - return envFroms, err - } - } - } - return envFroms, nil -} - -func expandContainerPort(in []interface{}) ([]v1.ContainerPort, error) { - if len(in) == 0 { - return []v1.ContainerPort{}, nil - } - ports := make([]v1.ContainerPort, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if containerPort, ok := p["container_port"]; ok { - ports[i].ContainerPort = int32(containerPort.(int)) - } - if hostIP, ok := p["host_ip"]; ok { - ports[i].HostIP = hostIP.(string) - } - if hostPort, ok := p["host_port"]; ok { - ports[i].HostPort = int32(hostPort.(int)) - } - if name, ok := p["name"]; ok { - ports[i].Name = name.(string) - } - if protocol, ok := p["protocol"]; ok { - ports[i].Protocol = v1.Protocol(protocol.(string)) - } - } - return ports, nil -} - -func expandConfigMapKeyRef(r []interface{}) (*v1.ConfigMapKeySelector, error) { - if len(r) == 0 || r[0] == nil { - return &v1.ConfigMapKeySelector{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.ConfigMapKeySelector{} - - if v, ok := in["key"].(string); ok { - obj.Key = v - } - if v, ok := in["name"].(string); ok { - obj.Name = v - } - return obj, nil - -} -func expandFieldRef(r []interface{}) (*v1.ObjectFieldSelector, error) { - if len(r) == 0 || r[0] == nil { - return &v1.ObjectFieldSelector{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.ObjectFieldSelector{} - - if v, ok := in["api_version"].(string); ok { - obj.APIVersion = v - } - if v, ok := in["field_path"].(string); ok { - obj.FieldPath = v - } - return obj, nil -} -func expandResourceFieldRef(r []interface{}) (*v1.ResourceFieldSelector, error) { - if len(r) == 0 || r[0] == nil { - return &v1.ResourceFieldSelector{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.ResourceFieldSelector{} - - if v, ok := in["container_name"].(string); ok { - obj.ContainerName = v - } - if v, ok := in["resource"].(string); ok { - obj.Resource = v - } - return obj, nil -} - -func expandSecretRef(r []interface{}) (*v1.SecretEnvSource, error) { - if len(r) == 0 || r[0] == nil { - return &v1.SecretEnvSource{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.SecretEnvSource{} - - if v, ok := in["name"].(string); ok { - obj.Name = v - } - if v, ok := in["optional"]; ok { - obj.Optional = ptrToBool(v.(bool)) - } - - return obj, nil -} - -func expandSecretKeyRef(r []interface{}) (*v1.SecretKeySelector, error) { - if len(r) == 0 || r[0] == nil { - return &v1.SecretKeySelector{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.SecretKeySelector{} - - if v, ok := in["key"].(string); ok { - obj.Key = v - } - if v, ok := in["name"].(string); ok { - obj.Name = v - } - return obj, nil -} - -func expandEnvValueFrom(r []interface{}) (*v1.EnvVarSource, error) { - if len(r) == 0 || r[0] == nil { - return &v1.EnvVarSource{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.EnvVarSource{} - - var err error - if v, ok := in["config_map_key_ref"].([]interface{}); ok && len(v) > 0 { - obj.ConfigMapKeyRef, err = expandConfigMapKeyRef(v) - if err != nil { - return obj, err - } - } - if v, ok := in["field_ref"].([]interface{}); ok && len(v) > 0 { - obj.FieldRef, err = expandFieldRef(v) - if err != nil { - return obj, err - } - } - if v, ok := in["secret_key_ref"].([]interface{}); ok && len(v) > 0 { - obj.SecretKeyRef, err = expandSecretKeyRef(v) - if err != nil { - return obj, err - } - } - if v, ok := in["resource_field_ref"].([]interface{}); ok && len(v) > 0 { - obj.ResourceFieldRef, err = expandResourceFieldRef(v) - if err != nil { - return obj, err - } - } - return obj, nil - -} - -func expandConfigMapRef(r []interface{}) (*v1.ConfigMapEnvSource, error) { - if len(r) == 0 || r[0] == nil { - return &v1.ConfigMapEnvSource{}, nil - } - in := r[0].(map[string]interface{}) - obj := &v1.ConfigMapEnvSource{} - - if v, ok := in["name"].(string); ok { - obj.Name = v - } - if v, ok := in["optional"]; ok { - obj.Optional = ptrToBool(v.(bool)) - } - - return obj, nil -} - -func expandContainerResourceRequirements(l []interface{}) (v1.ResourceRequirements, error) { - if len(l) == 0 || l[0] == nil { - return v1.ResourceRequirements{}, nil - } - in := l[0].(map[string]interface{}) - obj := v1.ResourceRequirements{} - - fn := func(in []interface{}) (v1.ResourceList, error) { - for _, c := range in { - p := c.(map[string]interface{}) - if p["cpu"] == "" { - delete(p, "cpu") - } - if p["memory"] == "" { - delete(p, "memory") - } - return expandMapToResourceList(p) - } - return nil, nil - } - - var err error - if v, ok := in["limits"].([]interface{}); ok && len(v) > 0 { - obj.Limits, err = fn(v) - if err != nil { - return obj, err - } - } - - if v, ok := in["requests"].([]interface{}); ok && len(v) > 0 { - obj.Requests, err = fn(v) - if err != nil { - return obj, err - } - } - - return obj, nil -} diff --git a/kubernetes/structures_deployment.go b/kubernetes/structures_deployment.go deleted file mode 100644 index 7c8c10dee9..0000000000 --- a/kubernetes/structures_deployment.go +++ /dev/null @@ -1,129 +0,0 @@ -package kubernetes - -import ( - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/intstr" -) - -func flattenDeploymentSpec(in appsv1.DeploymentSpec) ([]interface{}, error) { - att := make(map[string]interface{}) - att["min_ready_seconds"] = in.MinReadySeconds - - if in.Replicas != nil { - att["replicas"] = *in.Replicas - } - - if in.ProgressDeadlineSeconds != nil { - att["progress_deadline_seconds"] = *in.ProgressDeadlineSeconds - } - - if in.RevisionHistoryLimit != nil { - att["revision_history_limit"] = *in.RevisionHistoryLimit - } - - if in.Selector != nil { - att["selector"] = flattenLabelSelector(in.Selector) - } - - podSpec, err := flattenPodSpec(in.Template.Spec) - if err != nil { - return nil, err - } - template := make(map[string]interface{}) - template["spec"] = podSpec - template["metadata"] = flattenMetadata(in.Template.ObjectMeta) - att["template"] = []interface{}{template} - - return []interface{}{att}, nil -} - -func expandDeploymentSpec(deployment []interface{}) (appsv1.DeploymentSpec, error) { - obj := appsv1.DeploymentSpec{} - - if len(deployment) == 0 || deployment[0] == nil { - return obj, nil - } - - in := deployment[0].(map[string]interface{}) - - obj.MinReadySeconds = int32(in["min_ready_seconds"].(int)) - obj.Paused = in["paused"].(bool) - obj.ProgressDeadlineSeconds = ptrToInt32(int32(in["progress_deadline_seconds"].(int))) - obj.Replicas = ptrToInt32(int32(in["replicas"].(int))) - obj.RevisionHistoryLimit = ptrToInt32(int32(in["revision_history_limit"].(int))) - - if v, ok := in["selector"].([]interface{}); ok && len(v) > 0 { - obj.Selector = expandLabelSelector(v) - } - - if v, ok := in["strategy"].([]interface{}); ok && len(v) > 0 { - obj.Strategy = expandDeploymentStrategy(v) - } - - template, err := expandPodTemplate(in["template"].([]interface{})) - if err != nil { - return obj, err - } - obj.Template = template - - return obj, nil -} - -func expandPodTemplate(l []interface{}) (corev1.PodTemplateSpec, error) { - obj := corev1.PodTemplateSpec{} - if len(l) == 0 || l[0] == nil { - return obj, nil - } - in := l[0].(map[string]interface{}) - - obj.ObjectMeta = expandMetadata(in["metadata"].([]interface{})) - - if v, ok := in["spec"].([]interface{}); ok && len(v) > 0 { - podSpec, err := expandPodSpec(in["spec"].([]interface{})) - if err != nil { - return obj, err - } - obj.Spec = podSpec - } - return obj, nil -} - -func expandDeploymentStrategy(l []interface{}) appsv1.DeploymentStrategy { - if len(l) == 0 || l[0] == nil { - return appsv1.DeploymentStrategy{} - } - in := l[0].(map[string]interface{}) - obj := appsv1.DeploymentStrategy{} - if v, ok := in["type"].(map[string]interface{}); ok && len(v) > 0 { - obj.Type = appsv1.DeploymentStrategyType(in["type"].(string)) - } - if v, ok := in["rolling_update"].([]interface{}); ok && len(v) > 0 { - obj.RollingUpdate = expandRollingUpdateDeployment(v) - } - return obj -} - -func expandRollingUpdateDeployment(l []interface{}) *appsv1.RollingUpdateDeployment { - if len(l) == 0 || l[0] == nil { - return &appsv1.RollingUpdateDeployment{} - } - - in := l[0].(map[string]interface{}) - obj := &appsv1.RollingUpdateDeployment{} - if v, ok := in["max_surge"].(map[string]interface{}); ok && len(v) > 0 { - maxSurge := intstr.IntOrString{ - Type: intstr.String, - StrVal: in["max_surge"].(string), - } - obj.MaxSurge = &maxSurge - } - if v, ok := in["max_unavailable"].([]interface{}); ok && len(v) > 0 { - maxUnavailable := intstr.IntOrString{ - Type: intstr.String, - StrVal: in["max_unavailable"].(string), - } - obj.MaxUnavailable = &maxUnavailable - } - return obj -} diff --git a/kubernetes/structures_pod.go b/kubernetes/structures_pod.go deleted file mode 100644 index f7bf94fd8f..0000000000 --- a/kubernetes/structures_pod.go +++ /dev/null @@ -1,727 +0,0 @@ -package kubernetes - -import ( - "strconv" - - "github.com/hashicorp/terraform/helper/schema" - "k8s.io/api/core/v1" -) - -// Flatteners - -func flattenPodSpec(in v1.PodSpec) ([]interface{}, error) { - att := make(map[string]interface{}) - if in.ActiveDeadlineSeconds != nil { - att["active_deadline_seconds"] = *in.ActiveDeadlineSeconds - } - - containers, err := flattenContainers(in.Containers) - if err != nil { - return nil, err - } - att["container"] = containers - - initContainers, err := flattenContainers(in.InitContainers) - if err != nil { - return nil, err - } - att["init_container"] = initContainers - - att["dns_policy"] = in.DNSPolicy - - att["host_ipc"] = in.HostIPC - att["host_network"] = in.HostNetwork - att["host_pid"] = in.HostPID - - if in.Hostname != "" { - att["hostname"] = in.Hostname - } - att["image_pull_secrets"] = flattenLocalObjectReferenceArray(in.ImagePullSecrets) - - if in.NodeName != "" { - att["node_name"] = in.NodeName - } - if len(in.NodeSelector) > 0 { - att["node_selector"] = in.NodeSelector - } - if in.RestartPolicy != "" { - att["restart_policy"] = in.RestartPolicy - } - - if in.SecurityContext != nil { - att["security_context"] = flattenPodSecurityContext(in.SecurityContext) - } - if in.ServiceAccountName != "" { - att["service_account_name"] = in.ServiceAccountName - } - if in.Subdomain != "" { - att["subdomain"] = in.Subdomain - } - - if in.TerminationGracePeriodSeconds != nil { - att["termination_grace_period_seconds"] = *in.TerminationGracePeriodSeconds - } - - if len(in.Volumes) > 0 { - v, err := flattenVolumes(in.Volumes) - if err != nil { - return []interface{}{att}, err - } - att["volume"] = v - } - return []interface{}{att}, nil -} - -func flattenPodSecurityContext(in *v1.PodSecurityContext) []interface{} { - att := make(map[string]interface{}) - if in.FSGroup != nil { - att["fs_group"] = *in.FSGroup - } - - if in.RunAsNonRoot != nil { - att["run_as_non_root"] = *in.RunAsNonRoot - } - - if in.RunAsUser != nil { - att["run_as_user"] = *in.RunAsUser - } - - if len(in.SupplementalGroups) > 0 { - att["supplemental_groups"] = newInt64Set(schema.HashSchema(&schema.Schema{ - Type: schema.TypeInt, - }), in.SupplementalGroups) - } - if in.SELinuxOptions != nil { - att["se_linux_options"] = flattenSeLinuxOptions(in.SELinuxOptions) - } - - if len(att) > 0 { - return []interface{}{att} - } - return []interface{}{} -} - -func flattenSeLinuxOptions(in *v1.SELinuxOptions) []interface{} { - att := make(map[string]interface{}) - if in.User != "" { - att["user"] = in.User - } - if in.Role != "" { - att["role"] = in.Role - } - if in.User != "" { - att["type"] = in.Type - } - if in.Level != "" { - att["level"] = in.Level - } - return []interface{}{att} -} - -func flattenVolumes(volumes []v1.Volume) ([]interface{}, error) { - att := make([]interface{}, len(volumes)) - for i, v := range volumes { - obj := map[string]interface{}{} - - if v.Name != "" { - obj["name"] = v.Name - } - if v.ConfigMap != nil { - obj["config_map"] = flattenConfigMapVolumeSource(v.ConfigMap) - } - if v.GitRepo != nil { - obj["git_repo"] = flattenGitRepoVolumeSource(v.GitRepo) - } - if v.EmptyDir != nil { - obj["empty_dir"] = flattenEmptyDirVolumeSource(v.EmptyDir) - } - if v.DownwardAPI != nil { - obj["downward_api"] = flattenDownwardAPIVolumeSource(v.DownwardAPI) - } - if v.PersistentVolumeClaim != nil { - obj["persistent_volume_claim"] = flattenPersistentVolumeClaimVolumeSource(v.PersistentVolumeClaim) - } - if v.Secret != nil { - obj["secret"] = flattenSecretVolumeSource(v.Secret) - } - if v.GCEPersistentDisk != nil { - obj["gce_persistent_disk"] = flattenGCEPersistentDiskVolumeSource(v.GCEPersistentDisk) - } - if v.AWSElasticBlockStore != nil { - obj["aws_elastic_block_store"] = flattenAWSElasticBlockStoreVolumeSource(v.AWSElasticBlockStore) - } - if v.HostPath != nil { - obj["host_path"] = flattenHostPathVolumeSource(v.HostPath) - } - if v.Glusterfs != nil { - obj["glusterfs"] = flattenGlusterfsVolumeSource(v.Glusterfs) - } - if v.NFS != nil { - obj["nfs"] = flattenNFSVolumeSource(v.NFS) - } - if v.RBD != nil { - obj["rbd"] = flattenRBDVolumeSource(v.RBD) - } - if v.ISCSI != nil { - obj["iscsi"] = flattenISCSIVolumeSource(v.ISCSI) - } - if v.Cinder != nil { - obj["cinder"] = flattenCinderVolumeSource(v.Cinder) - } - if v.CephFS != nil { - obj["ceph_fs"] = flattenCephFSVolumeSource(v.CephFS) - } - if v.FC != nil { - obj["fc"] = flattenFCVolumeSource(v.FC) - } - if v.Flocker != nil { - obj["flocker"] = flattenFlockerVolumeSource(v.Flocker) - } - if v.FlexVolume != nil { - obj["flex_volume"] = flattenFlexVolumeSource(v.FlexVolume) - } - if v.AzureFile != nil { - obj["azure_file"] = flattenAzureFileVolumeSource(v.AzureFile) - } - if v.VsphereVolume != nil { - obj["vsphere_volume"] = flattenVsphereVirtualDiskVolumeSource(v.VsphereVolume) - } - if v.Quobyte != nil { - obj["quobyte"] = flattenQuobyteVolumeSource(v.Quobyte) - } - if v.AzureDisk != nil { - obj["azure_disk"] = flattenAzureDiskVolumeSource(v.AzureDisk) - } - if v.PhotonPersistentDisk != nil { - obj["photon_persistent_disk"] = flattenPhotonPersistentDiskVolumeSource(v.PhotonPersistentDisk) - } - att[i] = obj - } - return att, nil -} - -func flattenPersistentVolumeClaimVolumeSource(in *v1.PersistentVolumeClaimVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.ClaimName != "" { - att["claim_name"] = in.ClaimName - } - if in.ReadOnly { - att["read_only"] = in.ReadOnly - } - - return []interface{}{att} -} -func flattenGitRepoVolumeSource(in *v1.GitRepoVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.Directory != "" { - att["directory"] = in.Directory - } - - att["repository"] = in.Repository - - if in.Revision != "" { - att["revision"] = in.Revision - } - return []interface{}{att} -} - -func flattenDownwardAPIVolumeSource(in *v1.DownwardAPIVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.DefaultMode != nil { - att["default_mode"] = in.DefaultMode - } - if len(in.Items) > 0 { - att["items"] = flattenDownwardAPIVolumeFile(in.Items) - } - return []interface{}{att} -} - -func flattenDownwardAPIVolumeFile(in []v1.DownwardAPIVolumeFile) []interface{} { - att := make([]interface{}, len(in)) - for i, v := range in { - m := map[string]interface{}{} - if v.FieldRef != nil { - m["field_ref"] = flattenObjectFieldSelector(v.FieldRef) - } - if v.Mode != nil { - m["mode"] = *v.Mode - } - if v.Path != "" { - m["path"] = v.Path - } - if v.ResourceFieldRef != nil { - m["resource_field_ref"] = flattenResourceFieldSelector(v.ResourceFieldRef) - } - att[i] = m - } - return att -} - -func flattenConfigMapVolumeSource(in *v1.ConfigMapVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.DefaultMode != nil { - att["default_mode"] = *in.DefaultMode - } - att["name"] = in.Name - if len(in.Items) > 0 { - items := make([]interface{}, len(in.Items)) - for i, v := range in.Items { - m := map[string]interface{}{} - m["key"] = v.Key - m["mode"] = *v.Mode - m["path"] = v.Path - items[i] = m - } - att["items"] = items - } - - return []interface{}{att} -} - -func flattenEmptyDirVolumeSource(in *v1.EmptyDirVolumeSource) []interface{} { - att := make(map[string]interface{}) - att["medium"] = in.Medium - return []interface{}{att} -} - -func flattenSecretVolumeSource(in *v1.SecretVolumeSource) []interface{} { - att := make(map[string]interface{}) - if in.DefaultMode != nil { - att["default_mode"] = *in.DefaultMode - } - if in.SecretName != "" { - att["secret_name"] = in.SecretName - } - if len(in.Items) > 0 { - items := make([]interface{}, len(in.Items)) - for i, v := range in.Items { - m := map[string]interface{}{} - m["key"] = v.Key - if v.Mode != nil { - m["mode"] = int(*v.Mode) - } - m["path"] = v.Path - items[i] = m - } - att["items"] = items - } - if in.Optional != nil { - att["optional"] = *in.Optional - } - return []interface{}{att} -} - -// Expanders - -func expandPodSpec(p []interface{}) (v1.PodSpec, error) { - obj := v1.PodSpec{} - if len(p) == 0 || p[0] == nil { - return obj, nil - } - in := p[0].(map[string]interface{}) - - if v, ok := in["active_deadline_seconds"].(int); ok && v > 0 { - obj.ActiveDeadlineSeconds = ptrToInt64(int64(v)) - } - - if v, ok := in["container"].([]interface{}); ok && len(v) > 0 { - cs, err := expandContainers(v) - if err != nil { - return obj, err - } - obj.Containers = cs - } - - if v, ok := in["init_container"].([]interface{}); ok && len(v) > 0 { - cs, err := expandContainers(v) - if err != nil { - return obj, err - } - obj.InitContainers = cs - } - - if v, ok := in["dns_policy"].(string); ok { - obj.DNSPolicy = v1.DNSPolicy(v) - } - - if v, ok := in["host_ipc"]; ok { - obj.HostIPC = v.(bool) - } - - if v, ok := in["host_network"]; ok { - obj.HostNetwork = v.(bool) - } - - if v, ok := in["host_pid"]; ok { - obj.HostPID = v.(bool) - } - - if v, ok := in["hostname"]; ok { - obj.Hostname = v.(string) - } - - if v, ok := in["image_pull_secrets"].([]interface{}); ok { - cs := expandLocalObjectReferenceArray(v) - obj.ImagePullSecrets = cs - } - - if v, ok := in["node_name"]; ok { - obj.NodeName = v.(string) - } - - if v, ok := in["node_selector"].(map[string]interface{}); ok { - nodeSelectors := make(map[string]string) - for k, v := range v { - if val, ok := v.(string); ok { - nodeSelectors[k] = val - } - } - obj.NodeSelector = nodeSelectors - } - - if v, ok := in["restart_policy"].(string); ok { - obj.RestartPolicy = v1.RestartPolicy(v) - } - - if v, ok := in["security_context"].([]interface{}); ok && len(v) > 0 { - obj.SecurityContext = expandPodSecurityContext(v) - } - - if v, ok := in["service_account_name"].(string); ok { - obj.ServiceAccountName = v - } - - if v, ok := in["subdomain"].(string); ok { - obj.Subdomain = v - } - - if v, ok := in["termination_grace_period_seconds"].(int); ok { - obj.TerminationGracePeriodSeconds = ptrToInt64(int64(v)) - } - - if v, ok := in["volume"].([]interface{}); ok && len(v) > 0 { - cs, err := expandVolumes(v) - if err != nil { - return obj, err - } - obj.Volumes = cs - } - return obj, nil -} - -func expandPodSecurityContext(l []interface{}) *v1.PodSecurityContext { - if len(l) == 0 || l[0] == nil { - return &v1.PodSecurityContext{} - } - in := l[0].(map[string]interface{}) - obj := &v1.PodSecurityContext{} - if v, ok := in["fs_group"].(int); ok { - obj.FSGroup = ptrToInt64(int64(v)) - } - if v, ok := in["run_as_non_root"].(bool); ok { - obj.RunAsNonRoot = ptrToBool(v) - } - if v, ok := in["run_as_user"].(int); ok { - obj.RunAsUser = ptrToInt64(int64(v)) - } - if v, ok := in["supplemental_groups"].(*schema.Set); ok { - obj.SupplementalGroups = schemaSetToInt64Array(v) - } - - if v, ok := in["se_linux_options"].([]interface{}); ok && len(v) > 0 { - obj.SELinuxOptions = expandSeLinuxOptions(v) - } - - return obj -} - -func expandSeLinuxOptions(l []interface{}) *v1.SELinuxOptions { - if len(l) == 0 || l[0] == nil { - return &v1.SELinuxOptions{} - } - in := l[0].(map[string]interface{}) - obj := &v1.SELinuxOptions{} - if v, ok := in["level"]; ok { - obj.Level = v.(string) - } - if v, ok := in["role"]; ok { - obj.Role = v.(string) - } - if v, ok := in["type"]; ok { - obj.Type = v.(string) - } - if v, ok := in["user"]; ok { - obj.User = v.(string) - } - return obj -} - -func expandKeyPath(in []interface{}) []v1.KeyToPath { - if len(in) == 0 { - return []v1.KeyToPath{} - } - keyPaths := make([]v1.KeyToPath, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if v, ok := p["key"].(string); ok { - keyPaths[i].Key = v - } - if v, ok := p["mode"].(int); ok { - keyPaths[i].Mode = ptrToInt32(int32(v)) - } - if v, ok := p["path"].(string); ok { - keyPaths[i].Path = v - } - - } - return keyPaths -} - -func expandDownwardAPIVolumeFile(in []interface{}) ([]v1.DownwardAPIVolumeFile, error) { - var err error - if len(in) == 0 { - return []v1.DownwardAPIVolumeFile{}, nil - } - dapivf := make([]v1.DownwardAPIVolumeFile, len(in)) - for i, c := range in { - p := c.(map[string]interface{}) - if v, ok := p["mode"].(int); ok { - dapivf[i].Mode = ptrToInt32(int32(v)) - } - if v, ok := p["path"].(string); ok { - dapivf[i].Path = v - } - if v, ok := p["field_ref"].([]interface{}); ok && len(v) > 0 { - dapivf[i].FieldRef, err = expandFieldRef(v) - if err != nil { - return dapivf, err - } - } - if v, ok := p["resource_field_ref"].([]interface{}); ok && len(v) > 0 { - dapivf[i].ResourceFieldRef, err = expandResourceFieldRef(v) - if err != nil { - return dapivf, err - } - } - } - return dapivf, nil -} - -func expandConfigMapVolumeSource(l []interface{}) *v1.ConfigMapVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.ConfigMapVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.ConfigMapVolumeSource{ - DefaultMode: ptrToInt32(int32(in["default_mode"].(int))), - } - - if v, ok := in["name"].(string); ok { - obj.Name = v - } - - if v, ok := in["items"].([]interface{}); ok && len(v) > 0 { - obj.Items = expandKeyPath(v) - } - - return obj -} - -func expandDownwardAPIVolumeSource(l []interface{}) (*v1.DownwardAPIVolumeSource, error) { - if len(l) == 0 || l[0] == nil { - return &v1.DownwardAPIVolumeSource{}, nil - } - in := l[0].(map[string]interface{}) - obj := &v1.DownwardAPIVolumeSource{ - DefaultMode: ptrToInt32(int32(in["default_mode"].(int))), - } - if v, ok := in["items"].([]interface{}); ok && len(v) > 0 { - var err error - obj.Items, err = expandDownwardAPIVolumeFile(v) - if err != nil { - return obj, err - } - } - return obj, nil -} - -func expandGitRepoVolumeSource(l []interface{}) *v1.GitRepoVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.GitRepoVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.GitRepoVolumeSource{} - - if v, ok := in["directory"].(string); ok { - obj.Directory = v - } - - if v, ok := in["repository"].(string); ok { - obj.Repository = v - } - if v, ok := in["revision"].(string); ok { - obj.Revision = v - } - return obj -} - -func expandEmptyDirVolumeSource(l []interface{}) *v1.EmptyDirVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.EmptyDirVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.EmptyDirVolumeSource{ - Medium: v1.StorageMedium(in["medium"].(string)), - } - return obj -} - -func expandPersistentVolumeClaimVolumeSource(l []interface{}) *v1.PersistentVolumeClaimVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.PersistentVolumeClaimVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.PersistentVolumeClaimVolumeSource{ - ClaimName: in["claim_name"].(string), - ReadOnly: in["read_only"].(bool), - } - return obj -} - -func expandSecretVolumeSource(l []interface{}) *v1.SecretVolumeSource { - if len(l) == 0 || l[0] == nil { - return &v1.SecretVolumeSource{} - } - in := l[0].(map[string]interface{}) - obj := &v1.SecretVolumeSource{ - DefaultMode: ptrToInt32(int32(in["default_mode"].(int))), - SecretName: in["secret_name"].(string), - Optional: ptrToBool(in["optional"].(bool)), - } - - if v, ok := in["items"].([]interface{}); ok && len(v) > 0 { - obj.Items = expandKeyPath(v) - } - - return obj -} - -func expandVolumes(volumes []interface{}) ([]v1.Volume, error) { - if len(volumes) == 0 { - return []v1.Volume{}, nil - } - vl := make([]v1.Volume, len(volumes)) - for i, c := range volumes { - m := c.(map[string]interface{}) - - if value, ok := m["name"]; ok { - vl[i].Name = value.(string) - } - - if value, ok := m["config_map"].([]interface{}); ok && len(value) > 0 { - vl[i].ConfigMap = expandConfigMapVolumeSource(value) - } - if value, ok := m["git_repo"].([]interface{}); ok && len(value) > 0 { - vl[i].GitRepo = expandGitRepoVolumeSource(value) - } - - if value, ok := m["empty_dir"].([]interface{}); ok && len(value) > 0 { - vl[i].EmptyDir = expandEmptyDirVolumeSource(value) - } - if value, ok := m["downward_api"].([]interface{}); ok && len(value) > 0 { - var err error - vl[i].DownwardAPI, err = expandDownwardAPIVolumeSource(value) - if err != nil { - return vl, err - } - } - - if value, ok := m["persistent_volume_claim"].([]interface{}); ok && len(value) > 0 { - vl[i].PersistentVolumeClaim = expandPersistentVolumeClaimVolumeSource(value) - } - if value, ok := m["secret"].([]interface{}); ok && len(value) > 0 { - vl[i].Secret = expandSecretVolumeSource(value) - } - if v, ok := m["gce_persistent_disk"].([]interface{}); ok && len(v) > 0 { - vl[i].GCEPersistentDisk = expandGCEPersistentDiskVolumeSource(v) - } - if v, ok := m["aws_elastic_block_store"].([]interface{}); ok && len(v) > 0 { - vl[i].AWSElasticBlockStore = expandAWSElasticBlockStoreVolumeSource(v) - } - if v, ok := m["host_path"].([]interface{}); ok && len(v) > 0 { - vl[i].HostPath = expandHostPathVolumeSource(v) - } - if v, ok := m["glusterfs"].([]interface{}); ok && len(v) > 0 { - vl[i].Glusterfs = expandGlusterfsVolumeSource(v) - } - if v, ok := m["nfs"].([]interface{}); ok && len(v) > 0 { - vl[i].NFS = expandNFSVolumeSource(v) - } - if v, ok := m["rbd"].([]interface{}); ok && len(v) > 0 { - vl[i].RBD = expandRBDVolumeSource(v) - } - if v, ok := m["iscsi"].([]interface{}); ok && len(v) > 0 { - vl[i].ISCSI = expandISCSIVolumeSource(v) - } - if v, ok := m["cinder"].([]interface{}); ok && len(v) > 0 { - vl[i].Cinder = expandCinderVolumeSource(v) - } - if v, ok := m["ceph_fs"].([]interface{}); ok && len(v) > 0 { - vl[i].CephFS = expandCephFSVolumeSource(v) - } - if v, ok := m["fc"].([]interface{}); ok && len(v) > 0 { - vl[i].FC = expandFCVolumeSource(v) - } - if v, ok := m["flocker"].([]interface{}); ok && len(v) > 0 { - vl[i].Flocker = expandFlockerVolumeSource(v) - } - if v, ok := m["flex_volume"].([]interface{}); ok && len(v) > 0 { - vl[i].FlexVolume = expandFlexVolumeSource(v) - } - if v, ok := m["azure_file"].([]interface{}); ok && len(v) > 0 { - vl[i].AzureFile = expandAzureFileVolumeSource(v) - } - if v, ok := m["vsphere_volume"].([]interface{}); ok && len(v) > 0 { - vl[i].VsphereVolume = expandVsphereVirtualDiskVolumeSource(v) - } - if v, ok := m["quobyte"].([]interface{}); ok && len(v) > 0 { - vl[i].Quobyte = expandQuobyteVolumeSource(v) - } - if v, ok := m["azure_disk"].([]interface{}); ok && len(v) > 0 { - vl[i].AzureDisk = expandAzureDiskVolumeSource(v) - } - if v, ok := m["photon_persistent_disk"].([]interface{}); ok && len(v) > 0 { - vl[i].PhotonPersistentDisk = expandPhotonPersistentDiskVolumeSource(v) - } - } - return vl, nil -} - -func patchPodSpec(pathPrefix, prefix string, d *schema.ResourceData) (PatchOperations, error) { - ops := make([]PatchOperation, 0) - - if d.HasChange(prefix + "active_deadline_seconds") { - - v := d.Get(prefix + "active_deadline_seconds").(int) - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/activeDeadlineSeconds", - Value: v, - }) - } - - if d.HasChange(prefix + "container") { - containers := d.Get(prefix + "container").([]interface{}) - value, _ := expandContainers(containers) - - for i, v := range value { - ops = append(ops, &ReplaceOperation{ - Path: pathPrefix + "/containers/" + strconv.Itoa(i) + "/image", - Value: v.Image, - }) - - } - - } - - return ops, nil -} diff --git a/kubernetes/structures_rbac.go b/kubernetes/structures_rbac.go deleted file mode 100644 index 4f274e2c8b..0000000000 --- a/kubernetes/structures_rbac.go +++ /dev/null @@ -1,115 +0,0 @@ -package kubernetes - -import ( - "strconv" - - "github.com/hashicorp/terraform/helper/schema" - api "k8s.io/api/rbac/v1" -) - -func expandRBACRoleRef(in interface{}) api.RoleRef { - if in == nil { - return api.RoleRef{} - } - ref := api.RoleRef{} - m := in.(map[string]interface{}) - if v, ok := m["api_group"]; ok { - ref.APIGroup = v.(string) - } - if v, ok := m["kind"].(string); ok { - ref.Kind = string(v) - } - if v, ok := m["name"]; ok { - ref.Name = v.(string) - } - - return ref -} - -func expandRBACSubjects(in []interface{}) []api.Subject { - if len(in) == 0 || in[0] == nil { - return []api.Subject{} - } - subjects := make([]api.Subject, 0, len(in)) - for i := range in { - subject := api.Subject{} - m := in[i].(map[string]interface{}) - if v, ok := m["api_group"]; ok { - subject.APIGroup = v.(string) - } - if v, ok := m["kind"].(string); ok { - subject.Kind = string(v) - } - if v, ok := m["name"]; ok { - subject.Name = v.(string) - } - if v, ok := m["namespace"]; ok { - subject.Namespace = v.(string) - } - subjects = append(subjects, subject) - } - return subjects -} - -func flattenRBACRoleRef(in api.RoleRef) interface{} { - att := make(map[string]interface{}) - - if in.APIGroup != "" { - att["api_group"] = in.APIGroup - } - att["kind"] = in.Kind - att["name"] = in.Name - return att -} - -func flattenRBACSubjects(in []api.Subject) []interface{} { - att := make([]interface{}, 0, len(in)) - for _, n := range in { - m := make(map[string]interface{}) - if n.APIGroup != "" { - m["api_group"] = n.APIGroup - } - m["kind"] = n.Kind - m["name"] = n.Name - if n.Namespace != "" { - m["namespace"] = n.Namespace - } - att = append(att, m) - } - return att -} - -// Patch Ops -func patchRbacSubject(d *schema.ResourceData) PatchOperations { - o, n := d.GetChange("subject") - oldsubjects := expandRBACSubjects(o.([]interface{})) - newsubjects := expandRBACSubjects(n.([]interface{})) - ops := make([]PatchOperation, 0, len(newsubjects)+len(oldsubjects)) - - common := len(newsubjects) - if common > len(oldsubjects) { - common = len(oldsubjects) - } - for i, v := range newsubjects[:common] { - ops = append(ops, &ReplaceOperation{ - Path: "/subjects/" + strconv.Itoa(i), - Value: v, - }) - } - if len(oldsubjects) > len(newsubjects) { - for i := len(newsubjects); i < len(oldsubjects); i++ { - ops = append(ops, &RemoveOperation{ - Path: "/subjects/" + strconv.Itoa(len(oldsubjects)-i), - }) - } - } - if len(newsubjects) > len(oldsubjects) { - for i, v := range newsubjects[common:] { - ops = append(ops, &AddOperation{ - Path: "/subjects/" + strconv.Itoa(common+i), - Value: v, - }) - } - } - return ops -} diff --git a/kubernetes/structures_replication_controller.go b/kubernetes/structures_replication_controller.go deleted file mode 100644 index 5e7df92c56..0000000000 --- a/kubernetes/structures_replication_controller.go +++ /dev/null @@ -1,47 +0,0 @@ -package kubernetes - -import ( - "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func flattenReplicationControllerSpec(in v1.ReplicationControllerSpec) ([]interface{}, error) { - att := make(map[string]interface{}) - att["min_ready_seconds"] = in.MinReadySeconds - - if in.Replicas != nil { - att["replicas"] = *in.Replicas - } - - att["selector"] = in.Selector - podSpec, err := flattenPodSpec(in.Template.Spec) - if err != nil { - return nil, err - } - att["template"] = podSpec - - return []interface{}{att}, nil -} - -func expandReplicationControllerSpec(rc []interface{}) (v1.ReplicationControllerSpec, error) { - obj := v1.ReplicationControllerSpec{} - if len(rc) == 0 || rc[0] == nil { - return obj, nil - } - in := rc[0].(map[string]interface{}) - obj.MinReadySeconds = int32(in["min_ready_seconds"].(int)) - obj.Replicas = ptrToInt32(int32(in["replicas"].(int))) - obj.Selector = expandStringMap(in["selector"].(map[string]interface{})) - podSpec, err := expandPodSpec(in["template"].([]interface{})) - if err != nil { - return obj, err - } - obj.Template = &v1.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: obj.Selector, - }, - Spec: podSpec, - } - - return obj, nil -} diff --git a/kubernetes/structures_test.go b/kubernetes/structures_test.go deleted file mode 100644 index a423c3f9a4..0000000000 --- a/kubernetes/structures_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package kubernetes - -import ( - "fmt" - "testing" -) - -func TestIsInternalKey(t *testing.T) { - testCases := []struct { - Key string - Expected bool - }{ - {"", false}, - {"anyKey", false}, - {"any.hostname.io", false}, - {"any.hostname.com/with/path", false}, - {"any.kubernetes.io", true}, - {"kubernetes.io", true}, - {"pv.kubernetes.io/any/path", true}, - } - for i, tc := range testCases { - t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - isInternal := isInternalKey(tc.Key) - if tc.Expected && isInternal != tc.Expected { - t.Fatalf("Expected %q to be internal", tc.Key) - } - if !tc.Expected && isInternal != tc.Expected { - t.Fatalf("Expected %q not to be internal", tc.Key) - } - }) - } -} diff --git a/main.go b/main.go index 6f237a05f1..48bb7d8524 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main import ( "github.com/hashicorp/terraform/plugin" - "github.com/terraform-providers/terraform-provider-kubernetes/kubernetes" + "github.com/lawrencegripper/terraform-provider-kubernetes-yaml/kubernetes" ) func main() {