Add some resources and data-resources, fix bugs

2.0
stSolo 3 years ago
parent 9379289e58
commit bf179b9d12

1
.gitignore vendored

@ -1,3 +1,4 @@
decort/vendor/ decort/vendor/
examples/ examples/
url_scrapping/
terraform-provider-decort* terraform-provider-decort*

@ -25,6 +25,8 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort package decort
import ( import (
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
) )
@ -43,7 +45,7 @@ func dataSourceGridRead(d *schema.ResourceData, m interface{}) error {
if err != nil { if err != nil {
return err return err
} }
d.SetId("1234") d.SetId(strconv.Itoa(grid.Id))
flattenGrid(d, grid) flattenGrid(d, grid)
return nil return nil

@ -25,19 +25,22 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort package decort
import ( import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
) )
func flattenGridList(gl GridList) []map[string]interface{} { func flattenGridList(gl GridList) []map[string]interface{} {
res := make([]map[string]interface{}, len(gl), len(gl)) res := make([]map[string]interface{}, 0)
for _, item := range gl { for _, item := range gl {
temp := map[string]interface{}{} temp := map[string]interface{}{
temp["name"] = item.Name "name": item.Name,
temp["flag"] = item.Flag "flag": item.Flag,
temp["gid"] = item.Gid "gid": item.Gid,
temp["guid"] = item.Guid "guid": item.Guid,
temp["location_code"] = item.LocationCode "location_code": item.LocationCode,
temp["id"] = item.Id "id": item.Id,
}
res = append(res, temp) res = append(res, temp)
} }
return res return res
@ -48,7 +51,8 @@ func dataSourceGridListRead(d *schema.ResourceData, m interface{}) error {
if err != nil { if err != nil {
return err return err
} }
d.SetId("1234") id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenGridList(gridList)) d.Set("items", flattenGridList(gridList))
return nil return nil

@ -25,26 +25,60 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort package decort
import ( import (
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
) )
func flattenImage(d *schema.ResourceData, image *Image) { func flattenImage(d *schema.ResourceData, image *Image) {
d.Set("name", image.Name) d.Set("name", image.Name)
d.Set("drivers", image.Drivers)
d.Set("url", image.Url) d.Set("url", image.Url)
d.Set("gid", image.Gid) d.Set("gid", image.Gid)
d.Set("image_id", image.ImageId) d.Set("image_id", image.ImageId)
d.Set("boot_type", image.Boottype) d.Set("boot_type", image.Boottype)
d.Set("image_type", image.Imagetype) d.Set("image_type", image.Imagetype)
d.Set("bootable", image.Bootable)
d.Set("sep_id", image.SepId) d.Set("sep_id", image.SepId)
d.Set("unc_path", image.UNCPath)
d.Set("link_to", image.LinkTo)
d.Set("status", image.Status)
d.Set("tech_status", image.TechStatus)
d.Set("version", image.Version)
d.Set("size", image.Size)
d.Set("enabled", image.Enabled)
d.Set("computeci_id", image.ComputeciId)
d.Set("pool_name", image.PoolName)
d.Set("username", image.Username)
d.Set("username_dl", image.UsernameDL)
d.Set("password", image.Password)
d.Set("password_dl", image.PasswordDL)
d.Set("account_id", image.AccountId)
d.Set("guid", image.Guid)
d.Set("milestones", image.Milestones)
d.Set("provider_name", image.ProviderName)
d.Set("purge_attempts", image.PurgeAttempts)
d.Set("reference_id", image.ReferenceId)
d.Set("res_id", image.ResId)
d.Set("res_name", image.ResName)
d.Set("rescuecd", image.Rescuecd)
d.Set("architecture", image.Architecture)
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
d.Set("meta", flattenMeta(image.Meta))
d.Set("desc", image.Desc)
d.Set("shared_with", image.SharedWith)
return return
} }
func dataSourceImageRead(d *schema.ResourceData, m interface{}) error { func dataSourceImageRead(d *schema.ResourceData, m interface{}) error {
image, err := utilityImageCheckPresence(d, m) image, err := utilityImageCheckPresence(d, m)
if err != nil { if err != nil {
return err return err
} }
d.SetId("1234") d.SetId(strconv.Itoa(image.Guid))
flattenImage(d, image) flattenImage(d, image)
return nil return nil
@ -77,6 +111,34 @@ func dataSourceImageSchemaMake() map[string]*schema.Schema {
Computed: true, Computed: true,
Description: "Image type linux, windows or other", Description: "Image type linux, windows or other",
}, },
"shared_with": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"drivers": { "drivers": {
Type: schema.TypeList, Type: schema.TypeList,
Computed: true, Computed: true,
@ -85,6 +147,14 @@ func dataSourceImageSchemaMake() map[string]*schema.Schema {
}, },
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]", Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
}, },
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "meta",
},
"hot_resize": { "hot_resize": {
Type: schema.TypeBool, Type: schema.TypeBool,
Computed: true, Computed: true,
@ -145,30 +215,84 @@ func dataSourceImageSchemaMake() map[string]*schema.Schema {
Computed: true, Computed: true,
Description: "Does this image boot OS", Description: "Does this image boot OS",
}, },
"virtual": { "unc_path": {
Type: schema.TypeMap, Type: schema.TypeString,
Computed: true, Computed: true,
Description: "Create virtual image", Description: "unc path",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "name of the virtual image to create",
},
"v_image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "",
},
},
},
}, },
"link_to": { "link_to": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
Description: "", Description: "",
}, },
"status": {
Type: schema.TypeString,
Computed: true,
Description: "status",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "tech atatus",
},
"version": {
Type: schema.TypeString,
Computed: true,
Description: "version",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "image size",
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"computeci_id": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
} }
} }

@ -25,20 +25,53 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort package decort
import ( import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
) )
func flattenImageList(il ImageList) []map[string]interface{} { func flattenImageList(il ImageList) []map[string]interface{} {
res := make([]map[string]interface{}, len(il), len(il)) res := make([]map[string]interface{}, 0)
for _, item := range il { for _, item := range il {
temp := map[string]interface{}{} temp := map[string]interface{}{
temp["name"] = item.Name "name": item.Name,
temp["url"] = item.Url "url": item.Url,
temp["gid"] = item.Gid "gid": item.Gid,
temp["drivers"] = item.Drivers "guid": item.Guid,
temp["image_id"] = item.ImageId "drivers": item.Drivers,
temp["boot_type"] = item.Boottype "image_id": item.ImageId,
temp["image_type"] = item.Imagetype "boot_type": item.Boottype,
"bootable": item.Bootable,
"image_type": item.Imagetype,
"status": item.Status,
"tech_status": item.TechStatus,
"version": item.Version,
"username": item.Username,
"username_dl": item.UsernameDL,
"password": item.Password,
"password_dl": item.PasswordDL,
"purge_attempts": item.PurgeAttempts,
"architecture": item.Architecture,
"account_id": item.AccountId,
"computeci_id": item.ComputeciId,
"enabled": item.Enabled,
"reference_id": item.ReferenceId,
"res_id": item.ResId,
"res_name": item.ResName,
"rescuecd": item.Rescuecd,
"provider_name": item.ProviderName,
"milestones": item.Milestones,
"size": item.Size,
"sep_id": item.SepId,
"link_to": item.LinkTo,
"unc_path": item.UNCPath,
"pool_name": item.PoolName,
"hot_resize": item.Hotresize,
"history": flattenHistory(item.History),
"last_modified": item.LastModified,
"meta": flattenMeta(item.Meta),
"desc": item.Desc,
"shared_with": item.SharedWith,
}
res = append(res, temp) res = append(res, temp)
} }
return res return res
@ -49,7 +82,8 @@ func dataSourceImageListRead(d *schema.ResourceData, m interface{}) error {
if err != nil { if err != nil {
return err return err
} }
d.SetId("1234") id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenImageList(imageList)) d.Set("items", flattenImageList(imageList))
return nil return nil
@ -82,7 +116,7 @@ func dataSourceImageListSchemaMake() map[string]*schema.Schema {
Computed: true, Computed: true,
Description: "image list", Description: "image list",
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: resourceImageSchemaMake(), Schema: dataSourceImageSchemaMake(),
}, },
}, },
} }

@ -0,0 +1,182 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func flattenImageListStacks(d *schema.ResourceData, stack ImageListStacks) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range stack {
t := map[string]interface{}{
"api_url": item.ApiURL,
"api_key": item.ApiKey,
"app_id": item.AppId,
"desc": item.Desc,
"drivers": item.Drivers,
"error": item.Error,
"guid": item.Guid,
"id": item.Id,
"images": item.Images,
"login": item.Login,
"name": item.Name,
"passwd": item.Passwd,
"reference_id": item.ReferenceId,
"status": item.Status,
"type": item.Type,
}
temp = append(temp, t)
}
return temp
}
func dataSourceImageListStacksRead(d *schema.ResourceData, m interface{}) error {
imageListStacks, err := utilityImageListStacksCheckPresence(d, m)
if err != nil {
return err
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenImageListStacks(d, imageListStacks))
return nil
}
func dataSourceImageListStackSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"api_url": {
Type: schema.TypeString,
Computed: true,
},
"api_key": {
Type: schema.TypeString,
Computed: true,
},
"app_id": {
Type: schema.TypeString,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"error": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"images": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"login": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"passwd": {
Type: schema.TypeString,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
}
}
func dataSourceImageListStacksSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"image_id": {
Type: schema.TypeInt,
Required: true,
Description: "image id",
},
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "page number",
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "page size",
},
"items": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: dataSourceImageListStackSchemaMake(),
},
Description: "items of stacks list",
},
}
}
func dataSourceImageListStacks() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Read: dataSourceImageListStacksRead,
Timeouts: &schema.ResourceTimeout{
Read: &Timeout30s,
Default: &Timeout60s,
},
Schema: dataSourceImageListStacksSchemaMake(),
}
}

@ -668,42 +668,101 @@ type SshKeyConfig struct {
UserShell string UserShell string
} }
///////////////// ////////////////////
// images api // IMAGE API //
//////////////////// ////////////////////
const imageCreateAPI = "/restmachine/cloudbroker/image/createImage" const imageCreateAPI = "/restmachine/cloudbroker/image/createImage"
const imageSyncCreateAPI = "/restmachine/cloudbroker/image/syncCreateImage"
const imageCreateVirtualAPI = "/restmachine/cloudbroker/image/createVirtual"
const imageCreateCDROMAPI = "/restmachine/cloudbroker/image/createCDROMImage"
const imageListStacksApi = "/restmachine/cloudbroker/image/listStacks"
const imageGetAPI = "/restmachine/cloudbroker/image/get" const imageGetAPI = "/restmachine/cloudbroker/image/get"
const imageListGetAPI = "/restmachine/cloudbroker/image/list" const imageListGetAPI = "/restmachine/cloudbroker/image/list"
const imageEditAPI = "/restmachine/cloudbroker/image/edit" const imageEditAPI = "/restmachine/cloudbroker/image/edit"
const imageDeleteAPI = "/restmachine/cloudbroker/image/delete" const imageDeleteAPI = "/restmachine/cloudbroker/image/delete"
const imageEditNameAPI = "/restmachine/cloudapi/image/rename" const imageDeleteCDROMAPI = "/restmachine/cloudbroker/image/deleteCDROMImage"
const imageLinkAPI = "/restmachine/cloudapi/image/link" const imageEnableAPI = "/restmachine/cloudbroker/image/enable"
const imageDisableAPI = "/restmachine/cloudbroker/image/disable"
const imageEditNameAPI = "/restmachine/cloudbroker/image/rename"
const imageLinkAPI = "/restmachine/cloudbroker/image/link"
const imageShareAPI = "/restmachine/cloudbroker/image/share"
const imageComputeciSetAPI = "/restmachine/cloudbroker/image/computeciSet"
const imageComputeciUnsetAPI = "/restmachine/cloudbroker/image/computeciUnset"
const imageUpdateNodesAPI = "/restmachine/cloudbroker/image/updateNodes"
const imageDeleteImagesAPI = "/restmachine/cloudbroker/image/deleteImages"
type History struct {
Guid string `json:"guid"`
Id int `json:"id"`
Timestamp int64 `json:"timestamp"`
}
type Image struct { type Image struct {
ImageId int `json:"id"` ImageId int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Url string `json:"url"` Url string `json:"url"`
Gid int `json:"gid"` Gid int `json:"gid"`
Boottype string `json:"bootType"` Guid int `json:"guid"`
Imagetype string `json:"imagetype"` Boottype string `json:"bootType"`
Drivers []string `json:"drivers"` Imagetype string `json:"type"`
Hotresize bool `json:"hotresize"` Drivers []string `json:"drivers"`
Bootable bool `json:"bootable"` Hotresize bool `json:"hotResize"`
Username string `json:"username"` Bootable bool `json:"bootable"`
Password string `json:"password"` Username string `json:"username"`
AccountId int `json:"accountId"` Password string `json:"password"`
UsernameDL string `json:"usernameDL"` AccountId int `json:"accountId"`
PasswordDL string `json:"passwordDL"` UsernameDL string `json:"usernameDL"`
SepId int `json:"sepId"` PasswordDL string `json:"passwordDL"`
PoolName string `json:"poolName"` SepId int `json:"sepId"`
Architecture string `json:"architecture"` PoolName string `json:"pool"`
Architecture string `json:"architecture"`
UNCPath string `json:"UNCPath"`
LinkTo int `json:"linkTo"`
Status string `json:"status"`
TechStatus string `json:"techStatus"`
Size int `json:"size"`
Version string `json:"version"`
Enabled bool `json:"enabled"`
ComputeciId int `json:"computeciId"`
Milestones int `json:"milestones"`
ProviderName string `json:"provider_name"`
PurgeAttempts int `json:"purgeAttempts"`
ReferenceId string `json:"referenceId"`
ResId string `json:"resId"`
ResName string `json:"resName"`
Rescuecd bool `json:"rescuecd"`
Meta []interface{} `json:"_meta"`
History []History `json:"history"`
LastModified int64 `json:"lastModified"`
Desc string `json:"desc"`
SharedWith []int `json:"sharedWith"`
} }
type ImageList []Image type ImageList []Image
///////////// type ImageStack struct {
////GRID ApiURL string `json:"apiUrl"`
//////////////// ApiKey string `json:"apikey"`
AppId string `json:"appId"`
Desc string `json:"desc"`
Drivers []string `json:"drivers"`
Error int `json:"error"`
Guid int `json:"guid"`
Id int `json:"id"`
Images []int `json:"images"`
Login string `json:"login"`
Name string `json:"name"`
Passwd string `json:"passwd"`
ReferenceId string `json:"referenceId"`
Status string `json:"status"`
Type string `json:"type"`
}
type ImageListStacks []ImageStack
/////////////////
// GRID API //
/////////////////
const GridListGetAPI = "/restmachine/cloudbroker/grid/list" const GridListGetAPI = "/restmachine/cloudbroker/grid/list"
const GridGetAPI = "/restmachine/cloudbroker/grid/get" const GridGetAPI = "/restmachine/cloudbroker/grid/get"

@ -99,26 +99,30 @@ func Provider() *schema.Provider {
}, },
ResourcesMap: map[string]*schema.Resource{ ResourcesMap: map[string]*schema.Resource{
"decort_resgroup": resourceResgroup(), "decort_resgroup": resourceResgroup(),
"decort_kvmvm": resourceCompute(), "decort_kvmvm": resourceCompute(),
"decort_disk": resourceDisk(), "decort_disk": resourceDisk(),
"decort_vins": resourceVins(), "decort_vins": resourceVins(),
"decort_pfw": resourcePfw(), "decort_pfw": resourcePfw(),
"decort_k8s": resourceK8s(), "decort_k8s": resourceK8s(),
"decort_k8s_wg": resourceK8sWg(), "decort_k8s_wg": resourceK8sWg(),
"decort_image": resourceImage(), "decort_image": resourceImage(),
"decort_virtual_image": resourceVirtualImage(),
"decort_cdrom_image": resourceCDROMImage(),
"decort_delete_images": resourceDeleteImages(),
}, },
DataSourcesMap: map[string]*schema.Resource{ DataSourcesMap: map[string]*schema.Resource{
"decort_account": dataSourceAccount(), "decort_account": dataSourceAccount(),
"decort_resgroup": dataSourceResgroup(), "decort_resgroup": dataSourceResgroup(),
"decort_kvmvm": dataSourceCompute(), "decort_kvmvm": dataSourceCompute(),
"decort_image": dataSourceImage(), "decort_image": dataSourceImage(),
"decort_disk": dataSourceDisk(), "decort_disk": dataSourceDisk(),
"decort_vins": dataSourceVins(), "decort_vins": dataSourceVins(),
"decort_grid": dataSourceGrid(), "decort_grid": dataSourceGrid(),
"decort_grid_list": dataSourceGridList(), "decort_grid_list": dataSourceGridList(),
"decort_image_list": dataSourceImageList(), "decort_image_list": dataSourceImageList(),
"decort_image_list_stacks": dataSourceImageListStacks(),
// "decort_pfw": dataSourcePfw(), // "decort_pfw": dataSourcePfw(),
}, },

@ -0,0 +1,449 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceCDROMImageCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceCDROMImageCreate: called for image %s", d.Get("name").(string))
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("url", d.Get("url").(string))
urlValues.Add("gid", strconv.Itoa(d.Get("gid").(int)))
tstr := d.Get("drivers").([]interface{})
temp := ""
l := len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s
}
temp = "[" + temp + "]"
urlValues.Add("drivers", temp)
if username, ok := d.GetOk("username"); ok {
urlValues.Add("username", username.(string))
}
if password, ok := d.GetOk("password"); ok {
urlValues.Add("password", password.(string))
}
if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
}
if usernameDL, ok := d.GetOk("username_dl"); ok {
urlValues.Add("usernameDL", usernameDL.(string))
}
if passwordDL, ok := d.GetOk("password_dl"); ok {
urlValues.Add("passwordDL", passwordDL.(string))
}
if sepId, ok := d.GetOk("sep_id"); ok {
urlValues.Add("sepId", strconv.Itoa(sepId.(int)))
}
if poolName, ok := d.GetOk("pool_name"); ok {
urlValues.Add("pool_name", poolName.(string))
}
if architecture, ok := d.GetOk("architecture"); ok {
urlValues.Add("architecture", architecture.(string))
}
imageId, err := controller.decortAPICall("POST", imageCreateCDROMAPI, urlValues)
if err != nil {
return err
}
d.SetId(imageId)
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return err
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceCDROMImageDelete(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceCDROMImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
image, err := utilityImageCheckPresence(d, m)
if image == nil {
if err != nil {
return err
}
return nil
}
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if permanently, ok := d.GetOk("permanently"); ok {
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
}
_, err = controller.decortAPICall("POST", imageDeleteCDROMAPI, urlValues)
if err != nil {
return err
}
d.SetId("")
return nil
}
func resourceCDROMImageSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"url": {
Type: schema.TypeString,
Required: true,
Description: "URL where to download ISO from",
},
"gid": {
Type: schema.TypeInt,
Required: true,
Description: "grid (platform) ID where this template should be create in",
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
Description: "Boot type of image bios or uefi",
},
"image_type": {
Type: schema.TypeString,
Computed: true,
Description: "Image type linux, windows or other",
},
"drivers": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
},
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "meta",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
},
"password": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "AccountId to make the image exclusive",
},
"username_dl": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "username for upload binary media",
},
"password_dl": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "password for upload binary media",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"architecture": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "binary architecture of this image, one of X86_64 of PPC64_LE",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "image id",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Whether to completely delete the image",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this image boot OS",
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
Description: "unc path",
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
Description: "",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "status",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "tech atatus",
},
"version": {
Type: schema.TypeString,
Computed: true,
Description: "version",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "image size",
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"computeci_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"enabled_stacks": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
}
}
func resourceCDROMImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Create: resourceCDROMImageCreate,
Read: resourceImageRead,
Update: resourceImageEdit,
Delete: resourceCDROMImageDelete,
Exists: resourceImageExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName),
customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageUpdateNodes),
),
Schema: resourceCDROMImageSchemaMake(),
}
}

@ -0,0 +1,131 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"net/url"
"strconv"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceCreateListImages(d *schema.ResourceData, m interface{}) error {
id := uuid.New()
d.SetId(id.String())
return nil
}
func resourceDeleteListImages(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceDeleteListImages: start deleting...")
c := m.(*ControllerCfg)
urlValues := &url.Values{}
imageIds := d.Get("image_ids").([]interface{})
temp := ""
l := len(imageIds)
for i, imageId := range imageIds {
s := strconv.Itoa(imageId.(int))
if i != (l - 1) {
s += ",\n"
} else {
s += "\n"
}
temp = temp + s
}
temp = "[" + temp + "]"
urlValues.Add("reason", d.Get("reason").(string))
urlValues.Add("permanently", strconv.FormatBool(d.Get("permanently").(bool)))
urlValues.Add("imageIds", temp)
_, err := c.decortAPICall("POST", imageDeleteImagesAPI, urlValues)
if err != nil {
return err
}
d.SetId("")
return nil
}
func resourceReadListImages(d *schema.ResourceData, m interface{}) error {
return nil
}
func resourceDeleteImagesSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"image_ids": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
MinItems: 1,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
Description: "images ids for deleting",
},
"reason": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "reason for deleting the images",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: false,
Description: "whether to completely delete the images",
},
}
}
func resourceDeleteImages() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Create: resourceCreateListImages,
Read: resourceReadListImages,
Delete: resourceDeleteListImages,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
Schema: resourceDeleteImagesSchemaMake(),
}
}

@ -25,11 +25,12 @@ Visit https://github.com/rudecs/terraform-provider-decort for full source code p
package decort package decort
import ( import (
"errors"
"net/url" "net/url"
"strconv" "strconv"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
@ -46,8 +47,12 @@ func resourceImageCreate(d *schema.ResourceData, m interface{}) error {
tstr := d.Get("drivers").([]interface{}) tstr := d.Get("drivers").([]interface{})
temp := "" temp := ""
for _, str := range tstr { l := len(tstr)
for i, str := range tstr {
s := "\"" + str.(string) + "\"" s := "\"" + str.(string) + "\""
if i != (l - 1) {
s += ","
}
temp = temp + s temp = temp + s
} }
temp = "[" + temp + "]" temp = "[" + temp + "]"
@ -62,9 +67,6 @@ func resourceImageCreate(d *schema.ResourceData, m interface{}) error {
if password, ok := d.GetOk("password"); ok { if password, ok := d.GetOk("password"); ok {
urlValues.Add("password", password.(string)) urlValues.Add("password", password.(string))
} }
if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", accountId.(string))
}
if accountId, ok := d.GetOk("account_id"); ok { if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int))) urlValues.Add("accountId", strconv.Itoa(accountId.(int)))
} }
@ -84,7 +86,14 @@ func resourceImageCreate(d *schema.ResourceData, m interface{}) error {
urlValues.Add("architecture", architecture.(string)) urlValues.Add("architecture", architecture.(string))
} }
imageId, err := controller.decortAPICall("POST", imageCreateAPI, urlValues) api := ""
isSync := d.Get("sync").(bool)
if !isSync {
api = imageCreateAPI
} else {
api = imageSyncCreateAPI
}
imageId, err := controller.decortAPICall("POST", api, urlValues)
if err != nil { if err != nil {
return err return err
} }
@ -101,6 +110,11 @@ func resourceImageCreate(d *schema.ResourceData, m interface{}) error {
d.Set("bootable", image.Bootable) d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId) //d.Set("image_id", image.ImageId)
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil return nil
} }
@ -113,23 +127,44 @@ func resourceImageRead(d *schema.ResourceData, m interface{}) error {
return err return err
} }
d.Set("image_id", image.ImageId)
d.Set("name", image.Name) d.Set("name", image.Name)
d.Set("drivers", image.Drivers)
d.Set("url", image.Url) d.Set("url", image.Url)
d.Set("gid", image.Gid) d.Set("gid", image.Gid)
d.Set("image_id", image.ImageId)
d.Set("boot_type", image.Boottype) d.Set("boot_type", image.Boottype)
d.Set("image_type", image.Imagetype) d.Set("image_type", image.Imagetype)
d.Set("drivers", image.Drivers) d.Set("bootable", image.Bootable)
d.Set("hot_resize", image.Hotresize) d.Set("sep_id", image.SepId)
d.Set("unc_path", image.UNCPath)
d.Set("link_to", image.LinkTo)
d.Set("status", image.Status)
d.Set("tech_status", image.TechStatus)
d.Set("version", image.Version)
d.Set("size", image.Size)
d.Set("enabled", image.Enabled)
d.Set("computeci_id", image.ComputeciId)
d.Set("pool_name", image.PoolName)
d.Set("username", image.Username) d.Set("username", image.Username)
d.Set("password", image.Password)
d.Set("account_id", image.AccountId)
d.Set("username_dl", image.UsernameDL) d.Set("username_dl", image.UsernameDL)
d.Set("password", image.Password)
d.Set("password_dl", image.PasswordDL) d.Set("password_dl", image.PasswordDL)
d.Set("sep_id", image.SepId) d.Set("account_id", image.AccountId)
d.Set("pool_name", image.PoolName) d.Set("guid", image.Guid)
d.Set("milestones", image.Milestones)
d.Set("provider_name", image.ProviderName)
d.Set("purge_attempts", image.PurgeAttempts)
d.Set("reference_id", image.ReferenceId)
d.Set("res_id", image.ResId)
d.Set("res_name", image.ResName)
d.Set("rescuecd", image.Rescuecd)
d.Set("architecture", image.Architecture) d.Set("architecture", image.Architecture)
d.Set("bootable", image.Bootable) d.Set("meta", flattenMeta(image.Meta))
d.Set("hot_resize", image.Hotresize)
d.Set("history", flattenHistory(image.History))
d.Set("last_modified", image.LastModified)
d.Set("desc", image.Desc)
d.Set("shared_with", image.SharedWith)
return nil return nil
} }
@ -148,7 +183,11 @@ func resourceImageDelete(d *schema.ResourceData, m interface{}) error {
controller := m.(*ControllerCfg) controller := m.(*ControllerCfg)
urlValues := &url.Values{} urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int))) urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("reason", "") if reason, ok := d.GetOk("reason"); ok {
urlValues.Add("reason", reason.(string))
} else {
urlValues.Add("reason", "")
}
if permanently, ok := d.GetOk("permanently"); ok { if permanently, ok := d.GetOk("permanently"); ok {
urlValues.Add("permanently", strconv.FormatBool(permanently.(bool))) urlValues.Add("permanently", strconv.FormatBool(permanently.(bool)))
} }
@ -186,16 +225,71 @@ func resourceImageEditName(d *schema.ResourceDiff, m interface{}) error {
if err != nil { if err != nil {
return err return err
} }
return nil
}
func resourceImageEdit(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("username", d.Get("username").(string))
urlValues.Add("password", d.Get("password").(string))
urlValues.Add("accountId", strconv.Itoa(d.Get("account_id").(int)))
urlValues.Add("bootable", strconv.FormatBool(d.Get("bootable").(bool)))
urlValues.Add("hotresize", strconv.FormatBool(d.Get("hot_resize").(bool)))
//_, err := c.decortAPICall("POST", imageEditAPI, urlValues)
_, err := c.decortAPICall("POST", imageEditAPI, urlValues)
if err != nil {
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceImageChangeEnabled(d *schema.ResourceDiff, m interface{}) error {
var api string
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
if d.Get("enabled").(bool) {
api = imageEnableAPI
} else {
api = imageDisableAPI
}
resp, err := c.decortAPICall("POST", api, urlValues)
if err != nil {
return err
}
res, err := strconv.ParseBool(resp)
if err != nil {
return err
}
if !res {
return errors.New("Cannot enable/disable")
}
return nil return nil
} }
func resourceImageLink(d *schema.ResourceDiff, m interface{}) error { func resourceImageLink(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageLink: called for %s, id: %s", d.Get("name").(string), d.Id()) log.Debugf("resourceVirtualImageLink: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*ControllerCfg) c := m.(*ControllerCfg)
urlValues := &url.Values{} urlValues := &url.Values{}
link := d.Get("link").(map[string]interface{}) urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("imageId", strconv.Itoa(link["image_id"].(int))) urlValues.Add("targetId", strconv.Itoa(d.Get("link_to").(int)))
urlValues.Add("targetId", strconv.Itoa(link["target_id"].(int)))
_, err := c.decortAPICall("POST", imageLinkAPI, urlValues) _, err := c.decortAPICall("POST", imageLinkAPI, urlValues)
if err != nil { if err != nil {
return err return err
@ -204,31 +298,79 @@ func resourceImageLink(d *schema.ResourceDiff, m interface{}) error {
return nil return nil
} }
func resourceImageEdit(d *schema.ResourceData, m interface{}) error { func resourceImageShare(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageEdit: called for %s, id: %s", d.Get("name").(string), d.Id()) log.Debugf("resourceImageShare: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*ControllerCfg) c := m.(*ControllerCfg)
urlValues := &url.Values{} urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int))) urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
urlValues.Add("name", d.Get("name").(string)) accIds := d.Get("shared_with").([]interface{})
if username, ok := d.GetOk("username"); ok { temp := ""
urlValues.Add("username", username.(string)) l := len(accIds)
for i, accId := range accIds {
s := strconv.Itoa(accId.(int))
if i != (l - 1) {
s += ",\n"
} else {
s += "\n"
}
temp = temp + s
} }
if password, ok := d.GetOk("password"); ok { temp = "[" + temp + "]"
urlValues.Add("password", password.(string)) urlValues.Add("accounts", temp)
_, err := c.decortAPICall("POST", imageShareAPI, urlValues)
if err != nil {
return err
} }
if accountId, ok := d.GetOk("account_id"); ok {
urlValues.Add("accountId", strconv.Itoa(accountId.(int))) return nil
}
func resourceImageChangeComputeci(d *schema.ResourceDiff, m interface{}) error {
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
computeci := d.Get("computeci_id").(int)
api := ""
if computeci == 0 {
api = imageComputeciUnsetAPI
} else {
urlValues.Add("computeciId", strconv.Itoa(computeci))
api = imageComputeciSetAPI
} }
if bootable, ok := d.GetOk("bootable"); ok {
urlValues.Add("bootable", strconv.FormatBool(bootable.(bool))) _, err := c.decortAPICall("POST", api, urlValues)
if err != nil {
return err
} }
if hotresize, ok := d.GetOk("hot_resize"); ok {
urlValues.Add("hotresize", strconv.FormatBool(hotresize.(bool))) return nil
}
func resourceImageUpdateNodes(d *schema.ResourceDiff, m interface{}) error {
log.Debugf("resourceImageUpdateNodes: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
enabledStacks := d.Get("enabled_stacks").([]interface{})
temp := ""
l := len(enabledStacks)
for i, stackId := range enabledStacks {
s := stackId.(string)
if i != (l - 1) {
s += ","
}
temp = temp + s
} }
_, err := c.decortAPICall("POST", imageEditAPI, urlValues) temp = "[" + temp + "]"
urlValues.Add("enabledStacks", temp)
_, err := c.decortAPICall("POST", imageUpdateNodesAPI, urlValues)
if err != nil { if err != nil {
return err return err
} }
return nil return nil
} }
@ -237,129 +379,241 @@ func resourceImageSchemaMake() map[string]*schema.Schema {
"name": { "name": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true,
Description: "Name of the rescue disk", Description: "Name of the rescue disk",
}, },
"url": { "url": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true,
Description: "URL where to download media from", Description: "URL where to download media from",
}, },
"gid": { "gid": {
Type: schema.TypeInt, Type: schema.TypeInt,
Required: true, Required: true,
ForceNew: true, Description: "grid (platform) ID where this template should be create in",
ValidateFunc: validation.IntBetween(1, 65535),
Description: "grid (platform) ID where this template should be create in",
}, },
"boot_type": { "boot_type": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true, Description: "Boot type of image bios or uefi",
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, false),
Description: "Boot type of image bios or uefi",
}, },
"image_type": { "image_type": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Required: true,
ForceNew: true,
Description: "Image type linux, windows or other", Description: "Image type linux, windows or other",
}, },
"drivers": { "drivers": {
Type: schema.TypeList, Type: schema.TypeList,
Required: true, Required: true,
MinItems: 1,
Elem: &schema.Schema{ Elem: &schema.Schema{
Type: schema.TypeString, Type: schema.TypeString,
}, },
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]", Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
}, },
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "meta",
},
"hot_resize": { "hot_resize": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Computed: true,
Description: "Does this machine supports hot resize", Description: "Does this machine supports hot resize",
}, },
"username": { "username": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "Optional username for the image", Description: "Optional username for the image",
}, },
"password": { "password": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "Optional password for the image", Description: "Optional password for the image",
}, },
"account_id": { "account_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true,
Description: "AccountId to make the image exclusive", Description: "AccountId to make the image exclusive",
}, },
"username_dl": { "username_dl": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "username for upload binary media", Description: "username for upload binary media",
}, },
"password_dl": { "password_dl": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "password for upload binary media", Description: "password for upload binary media",
}, },
"sep_id": { "sep_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true, Optional: true,
Computed: true,
Description: "storage endpoint provider ID", Description: "storage endpoint provider ID",
}, },
"pool_name": { "pool_name": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
Computed: true,
Description: "pool for image create", Description: "pool for image create",
}, },
"architecture": { "architecture": {
Type: schema.TypeString, Type: schema.TypeString,
Optional: true, Optional: true,
ValidateFunc: validation.StringInSlice([]string{"X86_64", "PPC64_LE"}, false), Computed: true,
Description: "binary architecture of this image, one of X86_64 of PPC64_LE", Description: "binary architecture of this image, one of X86_64 of PPC64_LE",
}, },
"image_id": { "image_id": {
Type: schema.TypeInt, Type: schema.TypeInt,
Optional: true,
Computed: true, Computed: true,
Description: "image id", Description: "image id",
}, },
"permanently": { "permanently": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Computed: true,
Description: "Whether to completely delete the image", Description: "Whether to completely delete the image",
}, },
"bootable": { "bootable": {
Type: schema.TypeBool, Type: schema.TypeBool,
Optional: true, Optional: true,
Computed: true,
Description: "Does this image boot OS", Description: "Does this image boot OS",
}, },
"virtual": { "unc_path": {
Type: schema.TypeMap, Type: schema.TypeString,
Computed: true,
Description: "unc path",
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
Description: "",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "status",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "tech atatus",
},
"version": {
Type: schema.TypeString,
Computed: true,
Description: "version",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "image size",
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"computeci_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"reason": {
Type: schema.TypeString,
Optional: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"sync": {
Type: schema.TypeBool,
Optional: true, Optional: true,
Description: "Create virtual image", Default: false,
Description: "Create image from a media identified by URL (in synchronous mode)",
},
"enabled_stacks": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{ Elem: &schema.Resource{
Schema: map[string]*schema.Schema{ Schema: map[string]*schema.Schema{
"name": { "guid": {
Type: schema.TypeString, Type: schema.TypeString,
Required: true, Computed: true,
Description: "name of the virtual image to create", },
"id": {
Type: schema.TypeInt,
Computed: true,
}, },
"v_image_id": { "timestamp": {
Type: schema.TypeInt, Type: schema.TypeInt,
Computed: true, Computed: true,
Description: "",
}, },
}, },
}, },
}, },
"link_to": {
Type: schema.TypeInt,
Optional: true,
Description: "",
},
} }
} }
@ -384,20 +638,101 @@ func resourceImage() *schema.Resource {
Delete: &Timeout60s, Delete: &Timeout60s,
Default: &Timeout60s, Default: &Timeout60s,
}, },
/*CustomizeDiff: customdiff.All( CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool { customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
return !(old.(string) == new.(string)) if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName), }, resourceImageEditName),
customdiff.IfValueChange("link", func(old, new, meta interface{}) bool { customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.(map[string]interface{}) o := old.([]interface{})
n := new.(map[string]interface{}) n := new.([]interface{})
if o["image_id"].(int) != n["image_id"].(int) && o["target_id"].(int) != n["target_id"].(int) {
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true return true
} }
return false return false
}, resourceImageLink), }, resourceImageUpdateNodes),
),*/ ),
Schema: resourceImageSchemaMake(), Schema: resourceImageSchemaMake(),
} }
} }
func flattenMeta(m []interface{}) []string {
output := []string{}
for _, item := range m {
switch d := item.(type) {
case string:
output = append(output, d)
case int:
output = append(output, strconv.Itoa(d))
case int64:
output = append(output, strconv.FormatInt(d, 10))
case float64:
output = append(output, strconv.FormatInt(int64(d), 10))
default:
output = append(output, "")
}
}
return output
}
func flattenHistory(history []History) []map[string]interface{} {
temp := make([]map[string]interface{}, 0)
for _, item := range history {
t := map[string]interface{}{
"id": item.Id,
"guid": item.Guid,
"timestamp": item.Timestamp,
}
temp = append(temp, t)
}
return temp
}

@ -0,0 +1,402 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"net/url"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
log "github.com/sirupsen/logrus"
)
func resourceVirtualImageCreate(d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("name", d.Get("name").(string))
urlValues.Add("targetId", strconv.Itoa(d.Get("target_id").(int)))
imageId, err := controller.decortAPICall("POST", imageCreateVirtualAPI, urlValues)
if err != nil {
return err
}
d.SetId(imageId)
d.Set("image_id", imageId)
image, err := utilityImageCheckPresence(d, m)
if err != nil {
return err
}
d.SetId(strconv.Itoa(image.ImageId))
d.Set("bootable", image.Bootable)
//d.Set("image_id", image.ImageId)
err = resourceImageRead(d, m)
if err != nil {
return err
}
return nil
}
func resourceVirtualImageSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Description: "name of the virtual image to create",
},
"target_id": {
Type: schema.TypeInt,
Required: true,
Description: "ID of real image to link this virtual image to upon creation",
},
"history": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"guid": {
Type: schema.TypeString,
Computed: true,
},
"id": {
Type: schema.TypeInt,
Computed: true,
},
"timestamp": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"url": {
Type: schema.TypeString,
Computed: true,
Description: "URL where to download media from",
},
"gid": {
Type: schema.TypeInt,
Computed: true,
Description: "grid (platform) ID where this template should be create in",
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
Description: "Boot type of image bios or uefi",
},
"image_type": {
Type: schema.TypeString,
Computed: true,
Description: "Image type linux, windows or other",
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
},
"meta": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "meta",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"username": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
},
"password": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
},
"account_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "AccountId to make the image exclusive",
},
"username_dl": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "username for upload binary media",
},
"password_dl": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "password for upload binary media",
},
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"architecture": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "binary architecture of this image, one of X86_64 of PPC64_LE",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "image id",
},
"permanently": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Whether to completely delete the image",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this image boot OS",
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
Description: "unc path",
},
"link_to": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "status",
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
Description: "tech atatus",
},
"version": {
Type: schema.TypeString,
Computed: true,
Description: "version",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "image size",
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
},
"computeci_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"reference_id": {
Type: schema.TypeString,
Computed: true,
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"res_name": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"reason": {
Type: schema.TypeString,
Optional: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"enabled_stacks": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"shared_with": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
}
}
func resourceVirtualImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
Create: resourceVirtualImageCreate,
Read: resourceImageRead,
Update: resourceImageEdit,
Delete: resourceImageDelete,
Exists: resourceImageExists,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Create: &Timeout60s,
Read: &Timeout30s,
Update: &Timeout60s,
Delete: &Timeout60s,
Default: &Timeout60s,
},
CustomizeDiff: customdiff.All(
customdiff.IfValueChange("enabled", func(old, new, meta interface{}) bool {
if old.(bool) != new.(bool) {
return true
}
return false
}, resourceImageChangeEnabled),
customdiff.IfValueChange("link_to", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageLink),
customdiff.IfValueChange("name", func(old, new, meta interface{}) bool {
if old.(string) != new.(string) && old.(string) != "" {
return true
}
return false
}, resourceImageEditName),
customdiff.IfValueChange("shared_with", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(int) == o[i].(int) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageShare),
customdiff.IfValueChange("computeci_id", func(old, new, meta interface{}) bool {
if old.(int) != new.(int) {
return true
}
return false
}, resourceImageChangeComputeci),
customdiff.IfValueChange("enabled_stacks", func(old, new, meta interface{}) bool {
o := old.([]interface{})
n := new.([]interface{})
if len(o) != len(n) {
return true
} else if len(o) == 0 {
return false
}
count := 0
for i, v := range n {
if v.(string) == o[i].(string) {
count++
}
}
if count == 0 {
return true
}
return false
}, resourceImageUpdateNodes),
),
Schema: resourceVirtualImageSchemaMake(),
}
}

@ -55,7 +55,7 @@ func utilityImageCheckPresence(d *schema.ResourceData, m interface{}) (*Image, e
image := &Image{} image := &Image{}
if err := json.Unmarshal([]byte(resp), image); err != nil { if err := json.Unmarshal([]byte(resp), image); err != nil {
return nil, errors.New(fmt.Sprintf(resp, " ", image)) return nil, errors.New(fmt.Sprint("Can not unmarshall data to image: ", resp, " ", image))
} }
return image, nil return image, nil

@ -53,7 +53,7 @@ func utilityImageListCheckPresence(d *schema.ResourceData, m interface{}) (Image
urlValues.Add("size", strconv.Itoa(size.(int))) urlValues.Add("size", strconv.Itoa(size.(int)))
} }
log.Debugf("utilityGridListCheckPresence: load image list") log.Debugf("utilityImageListCheckPresence: load image list")
imageListRaw, err := controller.decortAPICall("POST", imageListGetAPI, urlValues) imageListRaw, err := controller.decortAPICall("POST", imageListGetAPI, urlValues)
if err != nil { if err != nil {
return nil, err return nil, err

@ -0,0 +1,56 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Author: Stanislav Solovev, <spsolovev@digitalenergy.online>, <svs1370@gmail.com>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
This file is part of Terraform (by Hashicorp) provider for Digital Energy Cloud Orchestration
Technology platfom.
Visit https://github.com/rudecs/terraform-provider-decort for full source code package and updates.
*/
package decort
import (
"encoding/json"
"net/url"
"strconv"
log "github.com/sirupsen/logrus"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
func utilityImageListStacksCheckPresence(d *schema.ResourceData, m interface{}) (ImageListStacks, error) {
imageListStacks := ImageListStacks{}
controller := m.(*ControllerCfg)
urlValues := &url.Values{}
urlValues.Add("imageId", strconv.Itoa(d.Get("image_id").(int)))
log.Debugf("utilityImageListStacksCheckPresence: load image list")
imageListRaw, err := controller.decortAPICall("POST", imageListStacksApi, urlValues)
if err != nil {
return nil, err
}
err = json.Unmarshal([]byte(imageListRaw), &imageListStacks)
if err != nil {
return nil, err
}
return imageListStacks, nil
}

@ -4,7 +4,7 @@ go 1.15
require ( require (
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/google/uuid v1.1.2 github.com/google/uuid v1.3.0
github.com/hashicorp/terraform-plugin-docs v0.5.1 github.com/hashicorp/terraform-plugin-docs v0.5.1
github.com/hashicorp/terraform-plugin-sdk v1.16.0 github.com/hashicorp/terraform-plugin-sdk v1.16.0
github.com/sirupsen/logrus v1.7.0 github.com/sirupsen/logrus v1.7.0

@ -171,6 +171,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=

Loading…
Cancel
Save