github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/builtin/providers/ignition/resource_ignition_config.go (about)

     1  package ignition
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/hashicorp/terraform/helper/schema"
     8  
     9  	"github.com/coreos/ignition/config/types"
    10  )
    11  
    12  var configReferenceResource = &schema.Resource{
    13  	Schema: map[string]*schema.Schema{
    14  		"source": &schema.Schema{
    15  			Type:     schema.TypeString,
    16  			ForceNew: true,
    17  			Required: true,
    18  		},
    19  		"verification": &schema.Schema{
    20  			Type:     schema.TypeString,
    21  			ForceNew: true,
    22  			Optional: true,
    23  		},
    24  	},
    25  }
    26  
    27  func resourceConfig() *schema.Resource {
    28  	return &schema.Resource{
    29  		Create: resourceIgnitionFileCreate,
    30  		Update: resourceIgnitionFileCreate,
    31  		Delete: resourceIgnitionFileDelete,
    32  		Exists: resourceIgnitionFileExists,
    33  		Read:   resourceIgnitionFileRead,
    34  		Schema: map[string]*schema.Schema{
    35  			"disks": &schema.Schema{
    36  				Type:     schema.TypeList,
    37  				Optional: true,
    38  				Elem:     &schema.Schema{Type: schema.TypeString},
    39  			},
    40  			"arrays": &schema.Schema{
    41  				Type:     schema.TypeList,
    42  				Optional: true,
    43  				Elem:     &schema.Schema{Type: schema.TypeString},
    44  			},
    45  			"filesystems": &schema.Schema{
    46  				Type:     schema.TypeList,
    47  				Optional: true,
    48  				Elem:     &schema.Schema{Type: schema.TypeString},
    49  			},
    50  			"files": &schema.Schema{
    51  				Type:     schema.TypeList,
    52  				Optional: true,
    53  				Elem:     &schema.Schema{Type: schema.TypeString},
    54  			},
    55  			"systemd": &schema.Schema{
    56  				Type:     schema.TypeList,
    57  				Optional: true,
    58  				Elem:     &schema.Schema{Type: schema.TypeString},
    59  			},
    60  			"networkd": &schema.Schema{
    61  				Type:     schema.TypeList,
    62  				Optional: true,
    63  				Elem:     &schema.Schema{Type: schema.TypeString},
    64  			},
    65  			"users": &schema.Schema{
    66  				Type:     schema.TypeList,
    67  				Optional: true,
    68  				Elem:     &schema.Schema{Type: schema.TypeString},
    69  			},
    70  			"groups": &schema.Schema{
    71  				Type:     schema.TypeList,
    72  				Optional: true,
    73  				Elem:     &schema.Schema{Type: schema.TypeString},
    74  			},
    75  			"replace": &schema.Schema{
    76  				Type:     schema.TypeList,
    77  				ForceNew: true,
    78  				Optional: true,
    79  				MaxItems: 1,
    80  				Elem:     configReferenceResource,
    81  			},
    82  			"append": &schema.Schema{
    83  				Type:     schema.TypeList,
    84  				ForceNew: true,
    85  				Optional: true,
    86  				Elem:     configReferenceResource,
    87  			},
    88  			"rendered": &schema.Schema{
    89  				Type:     schema.TypeString,
    90  				Computed: true,
    91  			},
    92  		},
    93  	}
    94  }
    95  
    96  func resourceIgnitionFileCreate(d *schema.ResourceData, meta interface{}) error {
    97  	rendered, err := renderConfig(d, meta.(*cache))
    98  	if err != nil {
    99  		return err
   100  	}
   101  
   102  	if err := d.Set("rendered", rendered); err != nil {
   103  		return err
   104  	}
   105  
   106  	d.SetId(hash(rendered))
   107  	return nil
   108  }
   109  
   110  func resourceIgnitionFileDelete(d *schema.ResourceData, meta interface{}) error {
   111  	d.SetId("")
   112  	return nil
   113  }
   114  
   115  func resourceIgnitionFileExists(d *schema.ResourceData, meta interface{}) (bool, error) {
   116  	rendered, err := renderConfig(d, meta.(*cache))
   117  	if err != nil {
   118  		return false, err
   119  	}
   120  
   121  	return hash(rendered) == d.Id(), nil
   122  }
   123  
   124  func resourceIgnitionFileRead(d *schema.ResourceData, meta interface{}) error {
   125  	return nil
   126  }
   127  
   128  func renderConfig(d *schema.ResourceData, c *cache) (string, error) {
   129  	i, err := buildConfig(d, c)
   130  	if err != nil {
   131  		return "", err
   132  	}
   133  
   134  	bytes, err := json.MarshalIndent(i, "  ", "  ")
   135  
   136  	if err != nil {
   137  		return "", err
   138  	}
   139  
   140  	return string(bytes), nil
   141  }
   142  
   143  func buildConfig(d *schema.ResourceData, c *cache) (*types.Config, error) {
   144  	var err error
   145  	config := &types.Config{}
   146  	config.Ignition, err = buildIgnition(d)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	config.Storage, err = buildStorage(d, c)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  
   156  	config.Systemd, err = buildSystemd(d, c)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  
   161  	config.Networkd, err = buildNetworkd(d, c)
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  
   166  	config.Passwd, err = buildPasswd(d, c)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  
   171  	return config, nil
   172  }
   173  
   174  func buildIgnition(d *schema.ResourceData) (types.Ignition, error) {
   175  	var err error
   176  
   177  	i := types.Ignition{}
   178  	i.Version.UnmarshalJSON([]byte(`"2.0.0"`))
   179  
   180  	rr := d.Get("replace.0").(map[string]interface{})
   181  	if len(rr) != 0 {
   182  		i.Config.Replace, err = buildConfigReference(rr)
   183  		if err != nil {
   184  			return i, err
   185  		}
   186  	}
   187  
   188  	ar := d.Get("append").([]interface{})
   189  	if len(ar) != 0 {
   190  		for _, rr := range ar {
   191  			r, err := buildConfigReference(rr.(map[string]interface{}))
   192  			if err != nil {
   193  				return i, err
   194  			}
   195  
   196  			i.Config.Append = append(i.Config.Append, *r)
   197  		}
   198  	}
   199  
   200  	return i, nil
   201  }
   202  
   203  func buildConfigReference(raw map[string]interface{}) (*types.ConfigReference, error) {
   204  	r := &types.ConfigReference{}
   205  
   206  	src, err := buildURL(raw["source"].(string))
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  
   211  	r.Source = src
   212  
   213  	hash, err := buildHash(raw["verification"].(string))
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  
   218  	r.Verification.Hash = &hash
   219  
   220  	return r, nil
   221  }
   222  
   223  func buildStorage(d *schema.ResourceData, c *cache) (types.Storage, error) {
   224  	storage := types.Storage{}
   225  
   226  	for _, id := range d.Get("disks").([]interface{}) {
   227  		d, ok := c.disks[id.(string)]
   228  		if !ok {
   229  			return storage, fmt.Errorf("invalid disk %q, unknown disk id", id)
   230  		}
   231  
   232  		storage.Disks = append(storage.Disks, *d)
   233  	}
   234  
   235  	for _, id := range d.Get("arrays").([]interface{}) {
   236  		a, ok := c.arrays[id.(string)]
   237  		if !ok {
   238  			return storage, fmt.Errorf("invalid raid %q, unknown raid id", id)
   239  		}
   240  
   241  		storage.Arrays = append(storage.Arrays, *a)
   242  	}
   243  
   244  	for _, id := range d.Get("filesystems").([]interface{}) {
   245  		f, ok := c.filesystems[id.(string)]
   246  		if !ok {
   247  			return storage, fmt.Errorf("invalid filesystem %q, unknown filesystem id", id)
   248  		}
   249  
   250  		storage.Filesystems = append(storage.Filesystems, *f)
   251  	}
   252  
   253  	for _, id := range d.Get("files").([]interface{}) {
   254  		f, ok := c.files[id.(string)]
   255  		if !ok {
   256  			return storage, fmt.Errorf("invalid file %q, unknown file id", id)
   257  		}
   258  
   259  		storage.Files = append(storage.Files, *f)
   260  	}
   261  
   262  	return storage, nil
   263  
   264  }
   265  
   266  func buildSystemd(d *schema.ResourceData, c *cache) (types.Systemd, error) {
   267  	systemd := types.Systemd{}
   268  
   269  	for _, id := range d.Get("systemd").([]interface{}) {
   270  		u, ok := c.systemdUnits[id.(string)]
   271  		if !ok {
   272  			return systemd, fmt.Errorf("invalid systemd unit %q, unknown systemd unit id", id)
   273  		}
   274  
   275  		systemd.Units = append(systemd.Units, *u)
   276  	}
   277  
   278  	return systemd, nil
   279  
   280  }
   281  
   282  func buildNetworkd(d *schema.ResourceData, c *cache) (types.Networkd, error) {
   283  	networkd := types.Networkd{}
   284  
   285  	for _, id := range d.Get("networkd").([]interface{}) {
   286  		u, ok := c.networkdUnits[id.(string)]
   287  		if !ok {
   288  			return networkd, fmt.Errorf("invalid networkd unit %q, unknown networkd unit id", id)
   289  		}
   290  
   291  		networkd.Units = append(networkd.Units, *u)
   292  	}
   293  
   294  	return networkd, nil
   295  }
   296  
   297  func buildPasswd(d *schema.ResourceData, c *cache) (types.Passwd, error) {
   298  	passwd := types.Passwd{}
   299  
   300  	for _, id := range d.Get("users").([]interface{}) {
   301  		u, ok := c.users[id.(string)]
   302  		if !ok {
   303  			return passwd, fmt.Errorf("invalid user %q, unknown user id", id)
   304  		}
   305  
   306  		passwd.Users = append(passwd.Users, *u)
   307  	}
   308  
   309  	for _, id := range d.Get("groups").([]interface{}) {
   310  		g, ok := c.groups[id.(string)]
   311  		if !ok {
   312  			return passwd, fmt.Errorf("invalid group %q, unknown group id", id)
   313  		}
   314  
   315  		passwd.Groups = append(passwd.Groups, *g)
   316  	}
   317  
   318  	return passwd, nil
   319  
   320  }