github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/builtin/providers/kubernetes/resource_kubernetes_pod.go (about) 1 package kubernetes 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "k8s.io/apimachinery/pkg/api/errors" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 pkgApi "k8s.io/apimachinery/pkg/types" 13 api "k8s.io/kubernetes/pkg/api/v1" 14 kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" 15 ) 16 17 func resourceKubernetesPod() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceKubernetesPodCreate, 20 Read: resourceKubernetesPodRead, 21 Update: resourceKubernetesPodUpdate, 22 Delete: resourceKubernetesPodDelete, 23 Exists: resourceKubernetesPodExists, 24 Importer: &schema.ResourceImporter{ 25 State: schema.ImportStatePassthrough, 26 }, 27 Schema: map[string]*schema.Schema{ 28 "metadata": namespacedMetadataSchema("pod", true), 29 "spec": { 30 Type: schema.TypeList, 31 Description: "Spec of the pod owned by the cluster", 32 Required: true, 33 MaxItems: 1, 34 Elem: &schema.Resource{ 35 Schema: podSpecFields(), 36 }, 37 }, 38 }, 39 } 40 } 41 func resourceKubernetesPodCreate(d *schema.ResourceData, meta interface{}) error { 42 conn := meta.(*kubernetes.Clientset) 43 44 metadata := expandMetadata(d.Get("metadata").([]interface{})) 45 spec, err := expandPodSpec(d.Get("spec").([]interface{})) 46 if err != nil { 47 return err 48 } 49 50 spec.AutomountServiceAccountToken = ptrToBool(false) 51 52 pod := api.Pod{ 53 ObjectMeta: metadata, 54 Spec: spec, 55 } 56 57 log.Printf("[INFO] Creating new pod: %#v", pod) 58 out, err := conn.CoreV1().Pods(metadata.Namespace).Create(&pod) 59 60 if err != nil { 61 return err 62 } 63 log.Printf("[INFO] Submitted new pod: %#v", out) 64 65 d.SetId(buildId(out.ObjectMeta)) 66 67 stateConf := &resource.StateChangeConf{ 68 Target: []string{"Running"}, 69 Pending: []string{"Pending"}, 70 Timeout: 5 * time.Minute, 71 Refresh: func() (interface{}, string, error) { 72 out, err := conn.CoreV1().Pods(metadata.Namespace).Get(metadata.Name, metav1.GetOptions{}) 73 if err != nil { 74 log.Printf("[ERROR] Received error: %#v", err) 75 return out, "Error", err 76 } 77 78 statusPhase := fmt.Sprintf("%v", out.Status.Phase) 79 log.Printf("[DEBUG] Pods %s status received: %#v", out.Name, statusPhase) 80 return out, statusPhase, nil 81 }, 82 } 83 _, err = stateConf.WaitForState() 84 if err != nil { 85 return err 86 } 87 log.Printf("[INFO] Pod %s created", out.Name) 88 89 return resourceKubernetesPodRead(d, meta) 90 } 91 92 func resourceKubernetesPodUpdate(d *schema.ResourceData, meta interface{}) error { 93 conn := meta.(*kubernetes.Clientset) 94 namespace, name := idParts(d.Id()) 95 ops := patchMetadata("metadata.0.", "/metadata/", d) 96 if d.HasChange("spec") { 97 specOps, err := patchPodSpec("/spec", "spec.0.", d) 98 if err != nil { 99 return err 100 } 101 ops = append(ops, specOps...) 102 } 103 data, err := ops.MarshalJSON() 104 if err != nil { 105 return fmt.Errorf("Failed to marshal update operations: %s", err) 106 } 107 108 log.Printf("[INFO] Updating pod %s: %s", d.Id(), ops) 109 110 out, err := conn.CoreV1().Pods(namespace).Patch(name, pkgApi.JSONPatchType, data) 111 if err != nil { 112 return err 113 } 114 log.Printf("[INFO] Submitted updated pod: %#v", out) 115 116 d.SetId(buildId(out.ObjectMeta)) 117 return resourceKubernetesPodRead(d, meta) 118 } 119 120 func resourceKubernetesPodRead(d *schema.ResourceData, meta interface{}) error { 121 conn := meta.(*kubernetes.Clientset) 122 namespace, name := idParts(d.Id()) 123 124 log.Printf("[INFO] Reading pod %s", name) 125 pod, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) 126 if err != nil { 127 log.Printf("[DEBUG] Received error: %#v", err) 128 return err 129 } 130 log.Printf("[INFO] Received pod: %#v", pod) 131 132 err = d.Set("metadata", flattenMetadata(pod.ObjectMeta)) 133 if err != nil { 134 return err 135 } 136 137 podSpec, err := flattenPodSpec(pod.Spec) 138 if err != nil { 139 return err 140 } 141 142 err = d.Set("spec", podSpec) 143 if err != nil { 144 return err 145 } 146 return nil 147 148 } 149 150 func resourceKubernetesPodDelete(d *schema.ResourceData, meta interface{}) error { 151 conn := meta.(*kubernetes.Clientset) 152 namespace, name := idParts(d.Id()) 153 log.Printf("[INFO] Deleting pod: %#v", name) 154 err := conn.CoreV1().Pods(namespace).Delete(name, nil) 155 if err != nil { 156 return err 157 } 158 159 err = resource.Retry(1*time.Minute, func() *resource.RetryError { 160 out, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) 161 if err != nil { 162 if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { 163 return nil 164 } 165 return resource.NonRetryableError(err) 166 } 167 168 log.Printf("[DEBUG] Current state of pod: %#v", out.Status.Phase) 169 e := fmt.Errorf("Pod %s still exists (%s)", name, out.Status.Phase) 170 return resource.RetryableError(e) 171 }) 172 if err != nil { 173 return err 174 } 175 176 log.Printf("[INFO] Pod %s deleted", name) 177 178 d.SetId("") 179 return nil 180 } 181 182 func resourceKubernetesPodExists(d *schema.ResourceData, meta interface{}) (bool, error) { 183 conn := meta.(*kubernetes.Clientset) 184 185 namespace, name := idParts(d.Id()) 186 log.Printf("[INFO] Checking pod %s", name) 187 _, err := conn.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{}) 188 if err != nil { 189 if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 { 190 return false, nil 191 } 192 log.Printf("[DEBUG] Received error: %#v", err) 193 } 194 return true, err 195 }