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  }