github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/scaleway/resource_scaleway_server.go (about)

     1  package scaleway
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  	"github.com/scaleway/scaleway-cli/pkg/api"
     9  )
    10  
    11  func resourceScalewayServer() *schema.Resource {
    12  	return &schema.Resource{
    13  		Create: resourceScalewayServerCreate,
    14  		Read:   resourceScalewayServerRead,
    15  		Update: resourceScalewayServerUpdate,
    16  		Delete: resourceScalewayServerDelete,
    17  		Importer: &schema.ResourceImporter{
    18  			State: schema.ImportStatePassthrough,
    19  		},
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"name": {
    23  				Type:     schema.TypeString,
    24  				Required: true,
    25  			},
    26  			"image": {
    27  				Type:     schema.TypeString,
    28  				Required: true,
    29  				ForceNew: true,
    30  			},
    31  			"type": {
    32  				Type:     schema.TypeString,
    33  				Required: true,
    34  				ForceNew: true,
    35  			},
    36  			"bootscript": {
    37  				Type:     schema.TypeString,
    38  				Optional: true,
    39  			},
    40  			"tags": {
    41  				Type: schema.TypeList,
    42  				Elem: &schema.Schema{
    43  					Type: schema.TypeString,
    44  				},
    45  				Optional: true,
    46  			},
    47  			"security_group": {
    48  				Type:     schema.TypeString,
    49  				Optional: true,
    50  			},
    51  			"volume": {
    52  				Type:     schema.TypeList,
    53  				Optional: true,
    54  				ForceNew: true,
    55  				Elem: &schema.Resource{
    56  					Schema: map[string]*schema.Schema{
    57  						"size_in_gb": {
    58  							Type:         schema.TypeInt,
    59  							Required:     true,
    60  							ValidateFunc: validateVolumeSize,
    61  						},
    62  						"type": {
    63  							Type:         schema.TypeString,
    64  							Required:     true,
    65  							ValidateFunc: validateVolumeType,
    66  						},
    67  						"volume_id": {
    68  							Type:     schema.TypeString,
    69  							Computed: true,
    70  						},
    71  					},
    72  				},
    73  			},
    74  			"enable_ipv6": {
    75  				Type:     schema.TypeBool,
    76  				Optional: true,
    77  				Default:  false,
    78  			},
    79  			"dynamic_ip_required": {
    80  				Type:     schema.TypeBool,
    81  				Optional: true,
    82  			},
    83  			"private_ip": {
    84  				Type:     schema.TypeString,
    85  				Computed: true,
    86  			},
    87  			"public_ip": {
    88  				Type:     schema.TypeString,
    89  				Optional: true,
    90  				Computed: true,
    91  			},
    92  			"public_ipv6": {
    93  				Type:     schema.TypeString,
    94  				Computed: true,
    95  			},
    96  			"state": {
    97  				Type:     schema.TypeString,
    98  				Optional: true,
    99  				Computed: true,
   100  			},
   101  			"state_detail": {
   102  				Type:     schema.TypeString,
   103  				Computed: true,
   104  			},
   105  		},
   106  	}
   107  }
   108  
   109  func resourceScalewayServerCreate(d *schema.ResourceData, m interface{}) error {
   110  	scaleway := m.(*Client).scaleway
   111  
   112  	mu.Lock()
   113  	defer mu.Unlock()
   114  
   115  	image := d.Get("image").(string)
   116  	var server = api.ScalewayServerDefinition{
   117  		Name:          d.Get("name").(string),
   118  		Image:         String(image),
   119  		Organization:  scaleway.Organization,
   120  		EnableIPV6:    d.Get("enable_ipv6").(bool),
   121  		SecurityGroup: d.Get("security_group").(string),
   122  	}
   123  
   124  	server.DynamicIPRequired = Bool(d.Get("dynamic_ip_required").(bool))
   125  	server.CommercialType = d.Get("type").(string)
   126  
   127  	if bootscript, ok := d.GetOk("bootscript"); ok {
   128  		server.Bootscript = String(bootscript.(string))
   129  	}
   130  
   131  	if vs, ok := d.GetOk("volume"); ok {
   132  		server.Volumes = make(map[string]string)
   133  
   134  		volumes := vs.([]interface{})
   135  		for i, v := range volumes {
   136  			volume := v.(map[string]interface{})
   137  
   138  			volumeID, err := scaleway.PostVolume(api.ScalewayVolumeDefinition{
   139  				Size: uint64(volume["size_in_gb"].(int)) * gb,
   140  				Type: volume["type"].(string),
   141  				Name: fmt.Sprintf("%s-%d", server.Name, volume["size_in_gb"].(int)),
   142  			})
   143  			if err != nil {
   144  				return err
   145  			}
   146  			volume["volume_id"] = volumeID
   147  			volumes[i] = volume
   148  			server.Volumes[fmt.Sprintf("%d", i+1)] = volumeID
   149  		}
   150  		d.Set("volume", volumes)
   151  	}
   152  
   153  	if raw, ok := d.GetOk("tags"); ok {
   154  		for _, tag := range raw.([]interface{}) {
   155  			server.Tags = append(server.Tags, tag.(string))
   156  		}
   157  	}
   158  
   159  	id, err := scaleway.PostServer(server)
   160  	if err != nil {
   161  		return err
   162  	}
   163  
   164  	d.SetId(id)
   165  	if d.Get("state").(string) != "stopped" {
   166  		err = scaleway.PostServerAction(id, "poweron")
   167  		if err != nil {
   168  			return err
   169  		}
   170  
   171  		err = waitForServerState(scaleway, id, "running")
   172  
   173  		if v, ok := d.GetOk("public_ip"); ok {
   174  			if ips, err := scaleway.GetIPS(); err != nil {
   175  				return err
   176  			} else {
   177  				for _, ip := range ips.IPS {
   178  					if ip.Address == v.(string) {
   179  						log.Printf("[DEBUG] Attaching IP %q to server %q\n", ip.ID, d.Id())
   180  						if err := scaleway.AttachIP(ip.ID, d.Id()); err != nil {
   181  							return err
   182  						}
   183  						break
   184  					}
   185  				}
   186  			}
   187  		}
   188  	}
   189  
   190  	if err != nil {
   191  		return err
   192  	}
   193  
   194  	return resourceScalewayServerRead(d, m)
   195  }
   196  
   197  func resourceScalewayServerRead(d *schema.ResourceData, m interface{}) error {
   198  	scaleway := m.(*Client).scaleway
   199  	server, err := scaleway.GetServer(d.Id())
   200  
   201  	if err != nil {
   202  		if serr, ok := err.(api.ScalewayAPIError); ok {
   203  			log.Printf("[DEBUG] Error reading server: %q\n", serr.APIMessage)
   204  
   205  			if serr.StatusCode == 404 {
   206  				d.SetId("")
   207  				return nil
   208  			}
   209  		}
   210  
   211  		return err
   212  	}
   213  
   214  	d.Set("name", server.Name)
   215  	d.Set("image", server.Image.Identifier)
   216  	d.Set("type", server.CommercialType)
   217  	d.Set("enable_ipv6", server.EnableIPV6)
   218  	d.Set("private_ip", server.PrivateIP)
   219  	d.Set("public_ip", server.PublicAddress.IP)
   220  
   221  	if server.EnableIPV6 {
   222  		d.Set("public_ipv6", server.IPV6.Address)
   223  	}
   224  
   225  	d.Set("state", server.State)
   226  	d.Set("state_detail", server.StateDetail)
   227  	d.Set("tags", server.Tags)
   228  
   229  	d.SetConnInfo(map[string]string{
   230  		"type": "ssh",
   231  		"host": server.PublicAddress.IP,
   232  	})
   233  
   234  	return nil
   235  }
   236  
   237  func resourceScalewayServerUpdate(d *schema.ResourceData, m interface{}) error {
   238  	scaleway := m.(*Client).scaleway
   239  
   240  	mu.Lock()
   241  	defer mu.Unlock()
   242  
   243  	var req api.ScalewayServerPatchDefinition
   244  	if d.HasChange("name") {
   245  		name := d.Get("name").(string)
   246  		req.Name = &name
   247  	}
   248  
   249  	if d.HasChange("tags") {
   250  		if raw, ok := d.GetOk("tags"); ok {
   251  			var tags []string
   252  			for _, tag := range raw.([]interface{}) {
   253  				tags = append(tags, tag.(string))
   254  			}
   255  			req.Tags = &tags
   256  		}
   257  	}
   258  
   259  	if d.HasChange("enable_ipv6") {
   260  		req.EnableIPV6 = Bool(d.Get("enable_ipv6").(bool))
   261  	}
   262  
   263  	if d.HasChange("dynamic_ip_required") {
   264  		req.DynamicIPRequired = Bool(d.Get("dynamic_ip_required").(bool))
   265  	}
   266  
   267  	if d.HasChange("security_group") {
   268  		req.SecurityGroup = &api.ScalewaySecurityGroup{
   269  			Identifier: d.Get("security_group").(string),
   270  		}
   271  	}
   272  
   273  	if err := scaleway.PatchServer(d.Id(), req); err != nil {
   274  		return fmt.Errorf("Failed patching scaleway server: %q", err)
   275  	}
   276  
   277  	if d.HasChange("public_ip") {
   278  		ips, err := scaleway.GetIPS()
   279  		if err != nil {
   280  			return err
   281  		}
   282  		if v, ok := d.GetOk("public_ip"); ok {
   283  			for _, ip := range ips.IPS {
   284  				if ip.Address == v.(string) {
   285  					log.Printf("[DEBUG] Attaching IP %q to server %q\n", ip.ID, d.Id())
   286  					if err := scaleway.AttachIP(ip.ID, d.Id()); err != nil {
   287  						return err
   288  					}
   289  					break
   290  				}
   291  			}
   292  		} else {
   293  			for _, ip := range ips.IPS {
   294  				if ip.Server != nil && ip.Server.Identifier == d.Id() {
   295  					log.Printf("[DEBUG] Detaching IP %q to server %q\n", ip.ID, d.Id())
   296  					if err := scaleway.DetachIP(ip.ID); err != nil {
   297  						return err
   298  					}
   299  					break
   300  				}
   301  			}
   302  		}
   303  	}
   304  
   305  	return resourceScalewayServerRead(d, m)
   306  }
   307  
   308  func resourceScalewayServerDelete(d *schema.ResourceData, m interface{}) error {
   309  	scaleway := m.(*Client).scaleway
   310  
   311  	mu.Lock()
   312  	defer mu.Unlock()
   313  
   314  	s, err := scaleway.GetServer(d.Id())
   315  	if err != nil {
   316  		return err
   317  	}
   318  
   319  	if s.State == "stopped" {
   320  		return deleteStoppedServer(scaleway, s)
   321  	}
   322  
   323  	err = deleteRunningServer(scaleway, s)
   324  
   325  	if err == nil {
   326  		d.SetId("")
   327  	}
   328  
   329  	return err
   330  }