github.com/koding/terraform@v0.6.4-0.20170608090606-5d7e0339779d/builtin/providers/rancher/resource_rancher_environment.go (about)

     1  package rancher
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  	"github.com/hashicorp/terraform/helper/validation"
    12  	rancherClient "github.com/rancher/go-rancher/client"
    13  )
    14  
    15  func resourceRancherEnvironment() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceRancherEnvironmentCreate,
    18  		Read:   resourceRancherEnvironmentRead,
    19  		Update: resourceRancherEnvironmentUpdate,
    20  		Delete: resourceRancherEnvironmentDelete,
    21  		Importer: &schema.ResourceImporter{
    22  			State: schema.ImportStatePassthrough,
    23  		},
    24  
    25  		Schema: map[string]*schema.Schema{
    26  			"id": &schema.Schema{
    27  				Type:     schema.TypeString,
    28  				Computed: true,
    29  			},
    30  			"name": &schema.Schema{
    31  				Type:     schema.TypeString,
    32  				Required: true,
    33  			},
    34  			"orchestration": &schema.Schema{
    35  				Type:         schema.TypeString,
    36  				Default:      "cattle",
    37  				Optional:     true,
    38  				ValidateFunc: validation.StringInSlice([]string{"cattle", "kubernetes", "mesos", "swarm"}, true),
    39  			},
    40  			"description": &schema.Schema{
    41  				Type:     schema.TypeString,
    42  				Optional: true,
    43  			},
    44  			"member": &schema.Schema{
    45  				Type:     schema.TypeSet,
    46  				Optional: true,
    47  				Computed: true,
    48  				Elem: &schema.Resource{
    49  					Schema: map[string]*schema.Schema{
    50  						"external_id_type": {
    51  							Type:     schema.TypeString,
    52  							Required: true,
    53  						},
    54  						"external_id": {
    55  							Type:     schema.TypeString,
    56  							Required: true,
    57  						},
    58  						"role": {
    59  							Type:     schema.TypeString,
    60  							Required: true,
    61  						},
    62  					},
    63  				},
    64  			},
    65  		},
    66  	}
    67  }
    68  
    69  func resourceRancherEnvironmentCreate(d *schema.ResourceData, meta interface{}) error {
    70  	log.Printf("[INFO] Creating Environment: %s", d.Id())
    71  	client, err := meta.(*Config).GlobalClient()
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	name := d.Get("name").(string)
    77  	description := d.Get("description").(string)
    78  	orchestration := d.Get("orchestration").(string)
    79  
    80  	data := map[string]interface{}{
    81  		"name":        &name,
    82  		"description": &description,
    83  	}
    84  
    85  	setOrchestrationFields(orchestration, data)
    86  
    87  	var newEnv rancherClient.Project
    88  	if err := client.Create("project", data, &newEnv); err != nil {
    89  		return err
    90  	}
    91  
    92  	stateConf := &resource.StateChangeConf{
    93  		Pending:    []string{"active", "removed", "removing"},
    94  		Target:     []string{"active"},
    95  		Refresh:    EnvironmentStateRefreshFunc(client, newEnv.Id),
    96  		Timeout:    10 * time.Minute,
    97  		Delay:      1 * time.Second,
    98  		MinTimeout: 3 * time.Second,
    99  	}
   100  	_, waitErr := stateConf.WaitForState()
   101  	if waitErr != nil {
   102  		return fmt.Errorf(
   103  			"Error waiting for environment (%s) to be created: %s", newEnv.Id, waitErr)
   104  	}
   105  
   106  	d.SetId(newEnv.Id)
   107  	log.Printf("[INFO] Environment ID: %s", d.Id())
   108  
   109  	// Add members
   110  	if v, ok := d.GetOk("member"); ok {
   111  		envClient, err := meta.(*Config).EnvironmentClient(d.Id())
   112  		if err != nil {
   113  			return err
   114  		}
   115  		members := v.([]interface{})
   116  		_, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{
   117  			Members: members,
   118  		})
   119  		if err != nil {
   120  			return err
   121  		}
   122  	}
   123  
   124  	return resourceRancherEnvironmentRead(d, meta)
   125  }
   126  
   127  func resourceRancherEnvironmentRead(d *schema.ResourceData, meta interface{}) error {
   128  	log.Printf("[INFO] Refreshing Environment: %s", d.Id())
   129  	client, err := meta.(*Config).GlobalClient()
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	env, err := client.Project.ById(d.Id())
   135  	if err != nil {
   136  		return err
   137  	}
   138  
   139  	if env == nil {
   140  		log.Printf("[INFO] Environment %s not found", d.Id())
   141  		d.SetId("")
   142  		return nil
   143  	}
   144  
   145  	if removed(env.State) {
   146  		log.Printf("[INFO] Environment %s was removed on %v", d.Id(), env.Removed)
   147  		d.SetId("")
   148  		return nil
   149  	}
   150  
   151  	log.Printf("[INFO] Environment Name: %s", env.Name)
   152  
   153  	d.Set("description", env.Description)
   154  	d.Set("name", env.Name)
   155  	d.Set("orchestration", getActiveOrchestration(env))
   156  
   157  	envClient, err := meta.(*Config).EnvironmentClient(d.Id())
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	members, _ := envClient.ProjectMember.List(NewListOpts())
   163  
   164  	d.Set("member", normalizeMembers(members.Data))
   165  	return nil
   166  }
   167  
   168  func resourceRancherEnvironmentUpdate(d *schema.ResourceData, meta interface{}) error {
   169  	client, err := meta.(*Config).GlobalClient()
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	name := d.Get("name").(string)
   175  	description := d.Get("description").(string)
   176  	orchestration := d.Get("orchestration").(string)
   177  
   178  	data := map[string]interface{}{
   179  		"name":        &name,
   180  		"description": &description,
   181  	}
   182  
   183  	setOrchestrationFields(orchestration, data)
   184  
   185  	var newEnv rancherClient.Project
   186  	env, err := client.Project.ById(d.Id())
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	if err := client.Update("project", &env.Resource, data, &newEnv); err != nil {
   192  		return err
   193  	}
   194  
   195  	// Update members
   196  	envClient, err := meta.(*Config).EnvironmentClient(d.Id())
   197  	if err != nil {
   198  		return err
   199  	}
   200  	members := d.Get("member").(*schema.Set).List()
   201  	_, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{
   202  		Members: makeProjectMembers(members),
   203  	})
   204  	if err != nil {
   205  		return err
   206  	}
   207  
   208  	return resourceRancherEnvironmentRead(d, meta)
   209  }
   210  
   211  func resourceRancherEnvironmentDelete(d *schema.ResourceData, meta interface{}) error {
   212  	log.Printf("[INFO] Deleting Environment: %s", d.Id())
   213  	id := d.Id()
   214  	client, err := meta.(*Config).GlobalClient()
   215  	if err != nil {
   216  		return err
   217  	}
   218  
   219  	env, err := client.Project.ById(id)
   220  	if err != nil {
   221  		return err
   222  	}
   223  
   224  	if err := client.Project.Delete(env); err != nil {
   225  		return fmt.Errorf("Error deleting Environment: %s", err)
   226  	}
   227  
   228  	log.Printf("[DEBUG] Waiting for environment (%s) to be removed", id)
   229  
   230  	stateConf := &resource.StateChangeConf{
   231  		Pending:    []string{"active", "removed", "removing"},
   232  		Target:     []string{"removed"},
   233  		Refresh:    EnvironmentStateRefreshFunc(client, id),
   234  		Timeout:    10 * time.Minute,
   235  		Delay:      1 * time.Second,
   236  		MinTimeout: 3 * time.Second,
   237  	}
   238  
   239  	_, waitErr := stateConf.WaitForState()
   240  	if waitErr != nil {
   241  		return fmt.Errorf(
   242  			"Error waiting for environment (%s) to be removed: %s", id, waitErr)
   243  	}
   244  
   245  	d.SetId("")
   246  	return nil
   247  }
   248  
   249  func setOrchestrationFields(orchestration string, data map[string]interface{}) {
   250  	orch := strings.ToLower(orchestration)
   251  
   252  	data["swarm"] = false
   253  	data["kubernetes"] = false
   254  	data["mesos"] = false
   255  
   256  	if orch == "k8s" {
   257  		orch = "kubernetes"
   258  	}
   259  
   260  	data[orch] = true
   261  }
   262  
   263  func normalizeMembers(in []rancherClient.ProjectMember) (out []interface{}) {
   264  	for _, m := range in {
   265  		mm := map[string]string{
   266  			"external_id_type": m.ExternalIdType,
   267  			"external_id":      m.ExternalId,
   268  			"role":             m.Role,
   269  		}
   270  		out = append(out, mm)
   271  	}
   272  	return
   273  }
   274  
   275  func makeProjectMembers(in []interface{}) (out []interface{}) {
   276  	for _, m := range in {
   277  		mMap := m.(map[string]interface{})
   278  		mm := rancherClient.ProjectMember{
   279  			ExternalIdType: mMap["external_id_type"].(string),
   280  			ExternalId:     mMap["external_id"].(string),
   281  			Role:           mMap["role"].(string),
   282  		}
   283  		out = append(out, mm)
   284  	}
   285  	return
   286  }
   287  
   288  // EnvironmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch
   289  // a Rancher Environment.
   290  func EnvironmentStateRefreshFunc(client *rancherClient.RancherClient, environmentID string) resource.StateRefreshFunc {
   291  	return func() (interface{}, string, error) {
   292  		env, err := client.Project.ById(environmentID)
   293  
   294  		if err != nil {
   295  			return nil, "", err
   296  		}
   297  
   298  		return env, env.State, nil
   299  	}
   300  }