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 }