github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/kubernetes/resource_kubernetes_persistent_volume.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  	meta_v1 "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 resourceKubernetesPersistentVolume() *schema.Resource {
    18  	return &schema.Resource{
    19  		Create: resourceKubernetesPersistentVolumeCreate,
    20  		Read:   resourceKubernetesPersistentVolumeRead,
    21  		Exists: resourceKubernetesPersistentVolumeExists,
    22  		Update: resourceKubernetesPersistentVolumeUpdate,
    23  		Delete: resourceKubernetesPersistentVolumeDelete,
    24  		Importer: &schema.ResourceImporter{
    25  			State: schema.ImportStatePassthrough,
    26  		},
    27  
    28  		Schema: map[string]*schema.Schema{
    29  			"metadata": metadataSchema("persistent volume", false),
    30  			"spec": {
    31  				Type:        schema.TypeList,
    32  				Description: "Spec of the persistent volume owned by the cluster",
    33  				Required:    true,
    34  				Elem: &schema.Resource{
    35  					Schema: map[string]*schema.Schema{
    36  						"access_modes": {
    37  							Type:        schema.TypeSet,
    38  							Description: "Contains all ways the volume can be mounted. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#access-modes",
    39  							Required:    true,
    40  							Elem:        &schema.Schema{Type: schema.TypeString},
    41  							Set:         schema.HashString,
    42  						},
    43  						"capacity": {
    44  							Type:         schema.TypeMap,
    45  							Description:  "A description of the persistent volume's resources and capacity. More info: http://kubernetes.io/docs/user-guide/persistent-volumes#capacity",
    46  							Required:     true,
    47  							Elem:         schema.TypeString,
    48  							ValidateFunc: validateResourceList,
    49  						},
    50  						"persistent_volume_reclaim_policy": {
    51  							Type:        schema.TypeString,
    52  							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",
    53  							Optional:    true,
    54  							Default:     "Retain",
    55  						},
    56  						"persistent_volume_source": {
    57  							Type:        schema.TypeList,
    58  							Description: "The specification of a persistent volume.",
    59  							Required:    true,
    60  							MaxItems:    1,
    61  							Elem:        persistentVolumeSourceSchema(),
    62  						},
    63  					},
    64  				},
    65  			},
    66  		},
    67  	}
    68  }
    69  
    70  func resourceKubernetesPersistentVolumeCreate(d *schema.ResourceData, meta interface{}) error {
    71  	conn := meta.(*kubernetes.Clientset)
    72  
    73  	metadata := expandMetadata(d.Get("metadata").([]interface{}))
    74  	spec, err := expandPersistentVolumeSpec(d.Get("spec").([]interface{}))
    75  	if err != nil {
    76  		return err
    77  	}
    78  	volume := api.PersistentVolume{
    79  		ObjectMeta: metadata,
    80  		Spec:       spec,
    81  	}
    82  
    83  	log.Printf("[INFO] Creating new persistent volume: %#v", volume)
    84  	out, err := conn.CoreV1().PersistentVolumes().Create(&volume)
    85  	if err != nil {
    86  		return err
    87  	}
    88  	log.Printf("[INFO] Submitted new persistent volume: %#v", out)
    89  
    90  	stateConf := &resource.StateChangeConf{
    91  		Target:  []string{"Available", "Bound"},
    92  		Pending: []string{"Pending"},
    93  		Timeout: 5 * time.Minute,
    94  		Refresh: func() (interface{}, string, error) {
    95  			out, err := conn.CoreV1().PersistentVolumes().Get(metadata.Name, meta_v1.GetOptions{})
    96  			if err != nil {
    97  				log.Printf("[ERROR] Received error: %#v", err)
    98  				return out, "Error", err
    99  			}
   100  
   101  			statusPhase := fmt.Sprintf("%v", out.Status.Phase)
   102  			log.Printf("[DEBUG] Persistent volume %s status received: %#v", out.Name, statusPhase)
   103  			return out, statusPhase, nil
   104  		},
   105  	}
   106  	_, err = stateConf.WaitForState()
   107  	if err != nil {
   108  		return err
   109  	}
   110  	log.Printf("[INFO] Persistent volume %s created", out.Name)
   111  
   112  	d.SetId(out.Name)
   113  
   114  	return resourceKubernetesPersistentVolumeRead(d, meta)
   115  }
   116  
   117  func resourceKubernetesPersistentVolumeRead(d *schema.ResourceData, meta interface{}) error {
   118  	conn := meta.(*kubernetes.Clientset)
   119  
   120  	name := d.Id()
   121  	log.Printf("[INFO] Reading persistent volume %s", name)
   122  	volume, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{})
   123  	if err != nil {
   124  		log.Printf("[DEBUG] Received error: %#v", err)
   125  		return err
   126  	}
   127  	log.Printf("[INFO] Received persistent volume: %#v", volume)
   128  	err = d.Set("metadata", flattenMetadata(volume.ObjectMeta))
   129  	if err != nil {
   130  		return err
   131  	}
   132  	err = d.Set("spec", flattenPersistentVolumeSpec(volume.Spec))
   133  	if err != nil {
   134  		return err
   135  	}
   136  
   137  	return nil
   138  }
   139  
   140  func resourceKubernetesPersistentVolumeUpdate(d *schema.ResourceData, meta interface{}) error {
   141  	conn := meta.(*kubernetes.Clientset)
   142  
   143  	ops := patchMetadata("metadata.0.", "/metadata/", d)
   144  	if d.HasChange("spec") {
   145  		specOps, err := patchPersistentVolumeSpec("/spec", "spec", d)
   146  		if err != nil {
   147  			return err
   148  		}
   149  		ops = append(ops, specOps...)
   150  	}
   151  	data, err := ops.MarshalJSON()
   152  	if err != nil {
   153  		return fmt.Errorf("Failed to marshal update operations: %s", err)
   154  	}
   155  
   156  	log.Printf("[INFO] Updating persistent volume %s: %s", d.Id(), ops)
   157  	out, err := conn.CoreV1().PersistentVolumes().Patch(d.Id(), pkgApi.JSONPatchType, data)
   158  	if err != nil {
   159  		return err
   160  	}
   161  	log.Printf("[INFO] Submitted updated persistent volume: %#v", out)
   162  	d.SetId(out.Name)
   163  
   164  	return resourceKubernetesPersistentVolumeRead(d, meta)
   165  }
   166  
   167  func resourceKubernetesPersistentVolumeDelete(d *schema.ResourceData, meta interface{}) error {
   168  	conn := meta.(*kubernetes.Clientset)
   169  
   170  	name := d.Id()
   171  	log.Printf("[INFO] Deleting persistent volume: %#v", name)
   172  	err := conn.CoreV1().PersistentVolumes().Delete(name, &meta_v1.DeleteOptions{})
   173  	if err != nil {
   174  		return err
   175  	}
   176  
   177  	log.Printf("[INFO] Persistent volume %s deleted", name)
   178  
   179  	d.SetId("")
   180  	return nil
   181  }
   182  
   183  func resourceKubernetesPersistentVolumeExists(d *schema.ResourceData, meta interface{}) (bool, error) {
   184  	conn := meta.(*kubernetes.Clientset)
   185  
   186  	name := d.Id()
   187  	log.Printf("[INFO] Checking persistent volume %s", name)
   188  	_, err := conn.CoreV1().PersistentVolumes().Get(name, meta_v1.GetOptions{})
   189  	if err != nil {
   190  		if statusErr, ok := err.(*errors.StatusError); ok && statusErr.ErrStatus.Code == 404 {
   191  			return false, nil
   192  		}
   193  		log.Printf("[DEBUG] Received error: %#v", err)
   194  	}
   195  	return true, err
   196  }