This commit is contained in:
2026-06-19 17:45:18 +03:00
parent c00c608ce9
commit 89c77ddcbe
1324 changed files with 199523 additions and 1 deletions

View File

@@ -0,0 +1,71 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func dataSourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
d.SetId(strconv.Itoa(int(image.ID)))
flattenImage(d, image)
return nil
}
func DataSourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceImageRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceImageExtendSchemaMake(),
}
}

View File

@@ -0,0 +1,175 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"github.com/google/uuid"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
)
func dataSourceImageListRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
imageList, err := utilityImageListCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
id := uuid.New()
d.SetId(id.String())
d.Set("items", flattenImageList(imageList))
d.Set("entry_count", imageList.EntryCount)
return nil
}
func dataSourceImageListSchemaMake() map[string]*schema.Schema {
rets := map[string]*schema.Schema{
"sep_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Filter by Storage Endpoint ID",
},
"by_id": {
Type: schema.TypeInt,
Optional: true,
Description: "Filter by ID",
},
"name": {
Type: schema.TypeString,
Optional: true,
Description: "Filter by name",
},
"status": {
Type: schema.TypeString,
Optional: true,
Description: "Filter by status",
},
"architecture": {
Type: schema.TypeString,
Optional: true,
Description: "Filter by architecture",
},
"type_image": {
Type: schema.TypeList,
Optional: true,
Description: "Filter by image type",
Elem: &schema.Schema{Type: schema.TypeString},
},
"image_size": {
Type: schema.TypeInt,
Optional: true,
Description: "Filter by image size",
},
"sep_name": {
Type: schema.TypeString,
Optional: true,
Description: "Filter by SEP name",
},
"pool": {
Type: schema.TypeString,
Optional: true,
Description: "Filter by pool",
},
"public": {
Type: schema.TypeBool,
Optional: true,
Description: "Find public/private images",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Description: "Find hot resizable images",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Description: "Find bootable images",
},
"sort_by": {
Type: schema.TypeString,
Optional: true,
Description: "sort by one of supported fields, format +|-(field)",
},
"page": {
Type: schema.TypeInt,
Optional: true,
Description: "page number",
},
"storage_policy_id": {
Type: schema.TypeInt,
Optional: true,
},
"size": {
Type: schema.TypeInt,
Optional: true,
Description: "page size",
},
"enabled": {
Type: schema.TypeBool,
Optional: true,
Description: "find by enabled True or False",
},
"items": {
Type: schema.TypeList,
Computed: true,
Description: "image list",
Elem: &schema.Resource{
Schema: dataSourceImageSchemaMake(),
},
},
"entry_count": {
Type: schema.TypeInt,
Computed: true,
},
}
return rets
}
func DataSourceImageList() *schema.Resource {
return &schema.Resource{
SchemaVersion: 1,
ReadContext: dataSourceImageListRead,
Timeouts: &schema.ResourceTimeout{
Read: &constants.Timeout30s,
Default: &constants.Timeout60s,
},
Schema: dataSourceImageListSchemaMake(),
}
}

View File

@@ -0,0 +1,115 @@
package image
import (
"encoding/json"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
)
func flattenHistory(history []image.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
}
func flattenImage(d *schema.ResourceData, img *image.RecordImage) {
cdPresentedTo, _ := json.Marshal(img.CdPresentedTo)
d.Set("unc_path", img.UNCPath)
d.Set("account_id", img.AccountID)
d.Set("acl", FlattenACL(img.ACL))
d.Set("architecture", img.Architecture)
d.Set("boot_type", img.BootType)
d.Set("bootable", img.Bootable)
d.Set("compute_ci_id", img.ComputeCIID)
d.Set("cd_presented_to", string(cdPresentedTo))
d.Set("deleted_time", img.DeletedTime)
d.Set("desc", img.Description)
d.Set("drivers", img.Drivers)
d.Set("enabled", img.Enabled)
d.Set("gid", img.GID)
d.Set("guid", img.GUID)
d.Set("history", flattenHistory(img.History))
d.Set("hot_resize", img.HotResize)
d.Set("image_id", img.ID)
d.Set("independent", img.Independent)
d.Set("last_modified", img.LastModified)
d.Set("link_to", img.LinkTo)
d.Set("links_to", img.LinksTo)
d.Set("milestones", img.Milestones)
d.Set("image_name", img.Name)
d.Set("network_interface_naming", img.NetworkInterfaceNaming)
d.Set("password", img.Password)
d.Set("pool_name", img.Pool)
d.Set("provider_name", img.ProviderName)
d.Set("purge_attempts", img.PurgeAttempts)
d.Set("present_to", img.PresentTo)
d.Set("res_id", img.ResID)
d.Set("rescuecd", img.RescueCD)
d.Set("sep_id", img.SepID)
d.Set("shared_with", img.SharedWith)
d.Set("size", img.Size)
d.Set("snapshot_id", img.SnapshotID)
d.Set("status", img.Status)
d.Set("storage_policy_id", img.StoragePolicyID)
d.Set("tech_status", img.TechStatus)
d.Set("to_clean", img.ToClean)
d.Set("image_type", img.Type)
d.Set("username", img.Username)
d.Set("version", img.Version)
}
func flattenImageList(il *image.ListImages) []map[string]interface{} {
res := make([]map[string]interface{}, 0)
for _, img := range il.Data {
temp := map[string]interface{}{
"account_id": img.AccountID,
"architecture": img.Architecture,
"boot_type": img.BootType,
"bootable": img.Bootable,
"cdrom": img.CDROM,
"desc": img.Description,
"drivers": img.Drivers,
"hot_resize": img.HotResize,
"image_id": img.ID,
"link_to": img.LinkTo,
"image_name": img.Name,
"network_interface_naming": img.NetworkInterfaceNaming,
"pool_name": img.Pool,
"sep_id": img.SepID,
"size": img.Size,
"status": img.Status,
"storage_policy_id": img.StoragePolicyID,
"image_type": img.Type,
"username": img.Username,
"virtual": img.Virtual,
}
res = append(res, temp)
}
return res
}
func FlattenACL(acl interface{}) string {
switch d := acl.(type) {
case string:
return d
case int:
return strconv.Itoa(d)
case int64:
return strconv.FormatInt(d, 10)
case float64:
return strconv.FormatInt(int64(d), 10)
default:
return ""
}
}

View File

@@ -0,0 +1,241 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
func dataSourceImageExtendSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"image_id": {
Type: schema.TypeInt,
Required: true,
},
"show_all": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"hot_resize": {
Type: schema.TypeBool,
Computed: true,
},
"independent": {
Type: schema.TypeBool,
Computed: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"links_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"password": {
Type: schema.TypeString,
Computed: true,
},
"pool_name": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"storage_policy_id": {
Type: schema.TypeInt,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"to_clean": {
Type: schema.TypeBool,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"username": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
}
}

View File

@@ -0,0 +1,148 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
func dataSourceImageSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"account_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Owner account id",
},
"architecture": {
Type: schema.TypeString,
Computed: true,
Description: "Image architecture",
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
Description: "Boot image type",
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
Description: "Flag, true if image is bootable, otherwise - false",
},
"cdrom": {
Type: schema.TypeBool,
Computed: true,
Description: "Flag, true if image is cdrom image, otherwise - false",
},
"desc": {
Type: schema.TypeString,
Computed: true,
Description: "Image description",
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
Description: "Image drivers",
},
"hot_resize": {
Type: schema.TypeBool,
Computed: true,
Description: "Flag, true if image supports hot resize, else if not",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Image id",
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
Description: "For virtual images, id image, which current image linked",
},
"links_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"image_name": {
Type: schema.TypeString,
Computed: true,
Description: "Image name",
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"pool_name": {
Type: schema.TypeString,
Computed: true,
Description: "Image pool",
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
Description: "Image storage endpoint id",
},
"size": {
Type: schema.TypeInt,
Computed: true,
Description: "Image size",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Image status",
},
"storage_policy_id": {
Type: schema.TypeInt,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
Description: "Image type",
},
"username": {
Type: schema.TypeString,
Computed: true,
Description: "username",
},
"virtual": {
Type: schema.TypeBool,
Computed: true,
Description: "True if image is virtula, otherwise - else",
},
}
}

View File

@@ -0,0 +1,150 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)
func resourceImageSchemaMake(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["url"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "URL where to download media from",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "image id",
}
sch["boot_type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image bios or uefi",
}
sch["type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "unknown"}, true),
Description: "Image type linux, windows or unknown",
}
sch["storage_policy_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "ID of the storage policy",
}
sch["hot_resize"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
}
sch["username"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
}
sch["password"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
}
sch["account_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "AccountId to make the image exclusive",
}
sch["username_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "username for upload binary media",
}
sch["password_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "password for upload binary media",
}
sch["pool_name"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
}
sch["sep_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
}
sch["network_interface_naming"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"eth", "ens"}, true),
Description: "select a network interface naming pattern for your Linux machine. eth - onboard, ens - pci slot naming",
}
sch["sync_mode"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "Create image from a media identified by URL (in synchronous mode)",
}
return sch
}

View File

@@ -0,0 +1,67 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func resourceImageVirtualSchemaMake(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["link_to"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "ID of real image to link this virtual image to upon creation",
}
sch["account_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "Account ID",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "Image id",
}
return sch
}

View File

@@ -0,0 +1,782 @@
package image
import (
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/statefuncs"
)
func resourceImageFromBlankComputeSchemaV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
Description: "Compute Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
},
"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",
},
"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",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceImageFromBlankDiskSchemaV1() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Required: true,
Description: "Disk Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
},
"architecture": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"X86_64"}, true),
Description: "binary architecture of this image, one of X86_64",
},
"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",
},
"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",
},
"drivers": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
StateFunc: statefuncs.StateFuncToUpper,
ValidateFunc: validation.StringInSlice([]string{"SVA_KVM_X86", "KVM_X86"}, false), // observe case while validating
Type: schema.TypeString,
},
Description: "List of types of compute suitable for image. Example: [ \"KVM_X86\" ]",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "bootable image",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
func dataSourceImageExtendSchemaV1() map[string]*schema.Schema {
return map[string]*schema.Schema{
"image_id": {
Type: schema.TypeInt,
Required: true,
},
"show_all": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"account_id": {
Type: schema.TypeInt,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"boot_type": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"hot_resize": {
Type: schema.TypeBool,
Computed: true,
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"password": {
Type: schema.TypeString,
Computed: true,
},
"pool_name": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
"username": {
Type: schema.TypeString,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
}
}
func resourceMainImageSchemaV1(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["url"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "URL where to download media from",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "image id",
}
sch["boot_type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image bios or uefi",
}
sch["type"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "other"}, true),
Description: "Image type linux, windows or other",
}
sch["hot_resize"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
}
sch["username"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional username for the image",
}
sch["password"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "Optional password for the image",
}
sch["account_id"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "AccountId to make the image exclusive",
}
sch["username_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "username for upload binary media",
}
sch["password_dl"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Description: "password for upload binary media",
}
sch["pool_name"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
}
sch["sep_id"] = &schema.Schema{
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "storage endpoint provider ID",
}
sch["architecture"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"X86_64"}, true),
Description: "binary architecture of this image, one of X86_64",
}
sch["drivers"] = &schema.Schema{
Type: schema.TypeList,
Required: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
}
sch["network_interface_naming"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
ValidateFunc: validation.StringInSlice([]string{"eth", "ens"}, true),
Description: "select a network interface naming pattern for your Linux machine. eth - onboard, ens - pci slot naming",
}
return sch
}
func resourceImageSchemaV1() *schema.Resource {
return &schema.Resource{Schema: resourceMainImageSchemaV1(dataSourceImageExtendSchemaV1())}
}
func resourceMainImageVirtualSchemaV1(sch map[string]*schema.Schema) map[string]*schema.Schema {
delete(sch, "show_all")
sch["name"] = &schema.Schema{
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
}
sch["link_to"] = &schema.Schema{
Type: schema.TypeInt,
Required: true,
Description: "ID of real image to link this virtual image to upon creation",
}
sch["image_id"] = &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "Image id",
}
return sch
}
func resourceImageVirtualSchemaV1() *schema.Resource {
return &schema.Resource{Schema: resourceMainImageVirtualSchemaV1(dataSourceImageExtendSchemaV1())}
}

View File

@@ -0,0 +1,89 @@
package image
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/account"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/disks"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/locations"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func existAccountID(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
c := m.(*controller.ControllerCfg)
accountId := uint64(d.Get("account_id").(int))
req := account.ListRequest{}
accounts, err := c.CloudAPI().Account().List(ctx, req)
if err != nil {
return false, err
}
return len(accounts.FilterByID(accountId).Data) != 0, nil
}
func existGID(ctx context.Context, d *schema.ResourceData, m interface{}) (bool, error) {
c := m.(*controller.ControllerCfg)
gid := uint64(d.Get("gid").(int))
req := locations.ListRequest{}
locationList, err := c.CloudAPI().Locations().List(ctx, req)
if err != nil {
return false, err
}
return len(locationList.FilterByGID(gid).Data) != 0, nil
}
func existComputeID(ctx context.Context, computeId uint64, m interface{}) error {
c := m.(*controller.ControllerCfg)
req := compute.GetRequest{ComputeID: computeId}
// check for compute existence
computeRecord, err := c.CloudAPI().Compute().Get(ctx, req)
if err != nil {
return fmt.Errorf("ComputeID %d is not allowed or does not exist", computeId)
}
// check if compute was created as blank
computeImageId := computeRecord.ImageID
bootImageId := -1
for _, d := range computeRecord.Disks {
if computeRecord.Chipset == "i440fx" {
if d.PCISlot == 6 {
bootImageId = int(d.ImageID)
break
}
} else {
if d.BusNumber == 6 {
bootImageId = int(d.ImageID)
break
}
}
}
if computeImageId != 0 && bootImageId != 0 {
return fmt.Errorf("ComputeID %d is not allowed because it is not blank compute (either compute imageId or boot imageId are not zero)", computeId)
}
return nil
}
func existDiskID(ctx context.Context, diskId uint64, m interface{}) error {
c := m.(*controller.ControllerCfg)
req := disks.ListRequest{ByID: diskId}
diskList, err := c.CloudAPI().Disks().List(ctx, req)
if err != nil {
return err
}
if len(diskList.Data) != 1 {
return fmt.Errorf("diskId %d is not allowed or doesn't exist", diskId)
}
return nil
}

View File

@@ -0,0 +1,303 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/tasks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/status"
)
func resourceImageCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageCreate: called for image %s", d.Get("name").(string))
haveAccountID, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccountID {
return diag.Errorf("resourceImageCreate: can't create Image because AccountID %d is not allowed or does not exist", d.Get("account_id").(int))
}
c := m.(*controller.ControllerCfg)
req := image.CreateRequest{
AccountID: uint64(d.Get("account_id").(int)),
Name: d.Get("name").(string),
URL: d.Get("url").(string),
BootType: d.Get("boot_type").(string),
ImageType: d.Get("type").(string),
StoragePolicyID: uint64(d.Get("storage_policy_id").(int)),
}
if hotresize, ok := d.GetOk("hot_resize"); ok {
req.HotResize = hotresize.(bool)
}
if username, ok := d.GetOk("username"); ok {
req.Username = username.(string)
}
if password, ok := d.GetOk("password"); ok {
req.Password = password.(string)
}
if usernameDL, ok := d.GetOk("username_dl"); ok {
req.UsernameDL = usernameDL.(string)
}
if passwordDL, ok := d.GetOk("password_dl"); ok {
req.PasswordDL = passwordDL.(string)
}
if sepId, ok := d.GetOk("sep_id"); ok {
req.SEPID = uint64(sepId.(int))
}
if poolName, ok := d.GetOk("pool_name"); ok {
req.Pool = poolName.(string)
}
if networkInterfaceNaming, ok := d.GetOk("network_interface_naming"); ok {
req.NetworkInterfaceNaming = networkInterfaceNaming.(string)
}
syncMode := d.Get("sync_mode").(bool)
var imageId uint64
if syncMode {
if err != nil {
return diag.FromErr(err)
}
imageId, err = c.CloudAPI().Image().Create(ctx, req)
log.Debugf("resourceImageCreate: imageID = %d", imageId)
if err != nil {
return diag.FromErr(err)
}
} else {
if err != nil {
return diag.FromErr(err)
}
taskID, err := c.CloudAPI().Image().AsyncCreate(ctx, req)
if err != nil {
return diag.FromErr(err)
}
taskReq := tasks.GetRequest{
AuditID: strings.Trim(taskID, `"`),
}
for {
time.Sleep(time.Second * 15)
task, err := c.CloudAPI().Tasks().Get(ctx, taskReq)
if err != nil {
return diag.FromErr(err)
}
log.Debugf("resourceAccountDelete: delete account - %s", task.Stage)
if task.Completed {
if task.Error != "" {
return diag.FromErr(fmt.Errorf("cannot delete account: %v", task.Error))
}
id, err := task.Result.ID()
imageId = uint64(id)
if err != nil {
return diag.FromErr(err)
}
break
}
}
}
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
_, err = utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
return resourceImageRead(ctx, d, m)
}
func resourceImageRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageRead: called for %s id: %s", d.Get("name").(string), d.Id())
img, err := utilityImageCheckPresence(ctx, d, m)
if img == nil {
d.SetId("")
return diag.FromErr(err)
}
switch img.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", img.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
// return resourceImageCreate(ctx, d, m)
}
flattenImage(d, img)
return nil
}
func resourceImageDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
_, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := image.DeleteRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
_, err = c.CloudAPI().Image().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceImageRename(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageEditName: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
req := image.RenameRequest{
ImageID: uint64(d.Get("image_id").(int)),
Name: d.Get("name").(string),
}
_, err := c.CloudAPI().Image().Rename(ctx, req)
if err != nil {
return err
}
return nil
}
func resourceImageUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageUpdate: called for %s, id: %s", d.Get("name").(string), d.Id())
haveGID, err := existGID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveGID {
return diag.Errorf("resourceImageUpdate: can't update Image because GID %d is not allowed or does not exist", d.Get("gid").(int))
}
haveAccountID, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccountID {
return diag.Errorf("resourceImageUpdate: can't update Image because AccountID %d is not allowed or does not exist", d.Get("account_id").(int))
}
image, err := utilityImageCheckPresence(ctx, d, m)
if image == nil {
if err != nil {
return diag.FromErr(err)
}
return nil
}
switch image.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", image.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
// return resourceImageCreate(ctx, d, m)
}
if d.HasChange("name") {
err := resourceImageRename(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
}
return resourceImageRead(ctx, d, m)
}
func ResourceImage() *schema.Resource {
return &schema.Resource{
SchemaVersion: 2,
CreateContext: resourceImageCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageUpdate,
DeleteContext: resourceImageDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout600s,
Read: &constants.Timeout300s,
Update: &constants.Timeout300s,
Delete: &constants.Timeout300s,
Default: &constants.Timeout300s,
},
Schema: resourceImageSchemaMake(dataSourceImageExtendSchemaMake()),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,522 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/compute"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/tasks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/status"
)
func resourceImageFromBlankComputeCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
computeId := uint64(d.Get("compute_id").(int))
name := d.Get("name").(string)
log.Debugf("resourceImageFromBlankComputeCreate: called for image %s", name)
err := existComputeID(ctx, computeId, m)
if err != nil {
return diag.Errorf("resourceImageFromBlankComputeCreate: can't create Image: %v", err)
}
if _, ok := d.GetOk("account_id"); ok {
haveAccountID, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccountID {
return diag.Errorf("resourceImageFromBlankComputeCreate: can't create Image because AccountID %d is not allowed or does not exist", d.Get("account_id").(int))
}
}
c := m.(*controller.ControllerCfg)
req := compute.CreateTemplateFromBlankRequest{
ComputeID: computeId,
Name: name,
BootType: d.Get("boot_type").(string),
ImageType: d.Get("type").(string),
StoragePolicyID: uint64(d.Get("storage_policy_id").(int)),
}
if username, ok := d.GetOk("username"); ok {
req.Username = username.(string)
}
if password, ok := d.GetOk("password"); ok {
req.Password = password.(string)
}
if accountId, ok := d.GetOk("account_id"); ok {
req.AccountID = uint64(accountId.(int))
}
if poolName, ok := d.GetOk("pool_name"); ok {
req.PoolName = poolName.(string)
}
if hotresize, ok := d.GetOk("hot_resize"); ok {
req.HotResize = hotresize.(bool)
}
var imageId uint64
asyncMode := d.Get("async_mode").(bool)
if !asyncMode {
imageId, err = c.CloudAPI().Compute().CreateTemplateFromBlank(ctx, req)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
} else {
taskId, err := c.CloudAPI().Compute().CreateTemplateFromBlankAsync(ctx, req)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
taskReq := tasks.GetRequest{
AuditID: strings.Trim(taskId, `"`),
}
for {
task, err := c.CloudAPI().Tasks().Get(ctx, taskReq)
if err != nil {
return diag.FromErr(err)
}
log.Debugf("resourceImageFromBlankComputeCreate: instance creating - %s", task.Stage)
if task.Completed {
if task.Error != "" {
return diag.FromErr(fmt.Errorf("cannot create image instance: %v", task.Error))
}
id, err := task.Result.ID()
imageId = uint64(id)
if err != nil {
return diag.FromErr(err)
}
break
}
time.Sleep(time.Second * 20)
}
}
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
_, err = utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
return resourceImageFromBlankComputeRead(ctx, d, m)
}
func resourceImageFromBlankComputeRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromBlankComputeRead: called for %s id: %s", d.Get("name").(string), d.Id())
img, err := utilityImageCheckPresence(ctx, d, m)
if img == nil {
d.SetId("")
return diag.FromErr(err)
}
switch img.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", img.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
// return resourceImageCreate(ctx, d, m)
}
flattenImage(d, img)
return nil
}
func resourceImageFromBlankComputeDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromBlankComputeDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
_, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := image.DeleteRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
_, err = c.CloudAPI().Image().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceImageFromBlankComputeRename(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceImageFromBlankComputeRename: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
req := image.RenameRequest{
ImageID: uint64(d.Get("image_id").(int)),
Name: d.Get("name").(string),
}
_, err := c.CloudAPI().Image().Rename(ctx, req)
if err != nil {
return err
}
return nil
}
func resourceImageFromBlankComputeUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromBlankComputeUpdate: called for %s, id: %s", d.Get("name").(string), d.Id())
// we do not allow change of compute_id, but allow resource update after import
old, _ := d.GetChange("compute_id")
if old.(int) != 0 && d.HasChange("compute_id") {
return diag.Errorf("resourceImageFromBlankComputeUpdate: can't update Image because compute_id is not allowed to be changed")
}
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
switch image.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", image.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
// return resourceImageCreate(ctx, d, m)
}
if d.HasChange("name") {
err := resourceImageFromBlankComputeRename(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
}
return resourceImageFromBlankComputeRead(ctx, d, m)
}
func ResourceImageFromBlankCompute() *schema.Resource {
return &schema.Resource{
SchemaVersion: 2,
CreateContext: resourceImageFromBlankComputeCreate,
ReadContext: resourceImageFromBlankComputeRead,
UpdateContext: resourceImageFromBlankComputeUpdate,
DeleteContext: resourceImageFromBlankComputeDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout30m,
Read: &constants.Timeout900s,
Update: &constants.Timeout900s,
Delete: &constants.Timeout900s,
Default: &constants.Timeout900s,
},
Schema: resourceImageFromBlankComputeSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromBlankComputeSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}
func resourceImageFromBlankComputeSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"compute_id": {
Type: schema.TypeInt,
Required: true,
Description: "Compute Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"storage_policy_id": {
Type: schema.TypeInt,
Required: true,
Description: "Storage policy ID",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "unknown"}, true),
Description: "Image type linux, windows or unknown",
},
"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",
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"bootable": {
Type: schema.TypeBool,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"links_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"to_clean": {
Type: schema.TypeBool,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
}
}

View File

@@ -0,0 +1,500 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/disks"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/tasks"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/status"
)
func resourceImageFromPlatformDiskCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
diskId := uint64(d.Get("disk_id").(int))
name := d.Get("name").(string)
log.Debugf("resourceImageFromPlatformDiskCreate: called for image %s", name)
err := existDiskID(ctx, diskId, m)
if err != nil {
return diag.Errorf("resourceImageFromPlatformDiskCreate: can't create Image: %v", err)
}
if _, ok := d.GetOk("account_id"); ok {
haveAccountID, err := existAccountID(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
if !haveAccountID {
return diag.Errorf("resourceImageFromPlatformDiskCreate: can't create Image because AccountID %d is not allowed or does not exist", d.Get("account_id").(int))
}
}
c := m.(*controller.ControllerCfg)
req := disks.FromPlatformDiskRequest{
DiskID: diskId,
Name: name,
BootType: d.Get("boot_type").(string),
ImageType: d.Get("type").(string),
Bootable: d.Get("bootable").(bool), // default value - true
}
if username, ok := d.GetOk("username"); ok {
req.Username = username.(string)
}
if password, ok := d.GetOk("password"); ok {
req.Password = password.(string)
}
if accountId, ok := d.GetOk("account_id"); ok {
req.AccountID = uint64(accountId.(int))
}
if poolName, ok := d.GetOk("pool_name"); ok {
req.PoolName = poolName.(string)
}
if hotresize, ok := d.GetOk("hot_resize"); ok {
req.HotResize = hotresize.(bool)
}
var imageId uint64
asyncMode := d.Get("async_mode").(bool)
if !asyncMode {
imageId, err = c.CloudAPI().Disks().FromPlatformDisk(ctx, req)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
} else {
taskId, err := c.CloudAPI().Disks().FromPlatformDiskAsync(ctx, req)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
taskReq := tasks.GetRequest{
AuditID: strings.Trim(taskId, `"`),
}
for {
task, err := c.CloudAPI().Tasks().Get(ctx, taskReq)
if err != nil {
return diag.FromErr(err)
}
log.Debugf("resourceImageFromPlatformDiskCreate: instance creating - %s", task.Stage)
if task.Completed {
if task.Error != "" {
return diag.FromErr(fmt.Errorf("cannot create image instance: %v", task.Error))
}
id, err := task.Result.ID()
imageId = uint64(id)
if err != nil {
return diag.FromErr(err)
}
break
}
time.Sleep(time.Second * 20)
}
}
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
_, err = utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
return resourceImageFromPlatformDiskRead(ctx, d, m)
}
func resourceImageFromPlatformDiskRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromPlatformDiskRead: called for %s id: %s", d.Get("name").(string), d.Id())
img, err := utilityImageCheckPresence(ctx, d, m)
if img == nil {
d.SetId("")
return diag.FromErr(err)
}
switch img.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", img.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
}
flattenImage(d, img)
return nil
}
func resourceImageFromPlatformDiskDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromPlatformDiskDelete: called for %s, id: %s", d.Get("name").(string), d.Id())
_, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
c := m.(*controller.ControllerCfg)
req := image.DeleteRequest{
ImageID: uint64(d.Get("image_id").(int)),
}
_, err = c.CloudAPI().Image().Delete(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}
func resourceImageFromPlatformDiskUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageFromPlatformDiskUpdate: called for %s, id: %s", d.Get("name").(string), d.Id())
// we do not allow change of disk_id, but allow resource update after import
old, _ := d.GetChange("disk_id")
if old.(int) != 0 && d.HasChange("disk_id") {
return diag.Errorf("resourceImageFromPlatformDiskUpdate: can't update Image because disk_id is not allowed to be changed")
}
image, err := utilityImageCheckPresence(ctx, d, m)
if err != nil {
d.SetId("")
return diag.FromErr(err)
}
switch image.Status {
case status.Modeled:
return diag.Errorf("The image is in status: %s, please, contact support for more information", image.Status)
case status.Creating:
case status.Created:
case status.Destroyed, status.Purged:
d.SetId("")
return diag.Errorf("The resource cannot be updated because it has been destroyed")
}
if d.HasChange("name") {
err := resourceImageRename(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
}
return resourceImageFromPlatformDiskRead(ctx, d, m)
}
func ResourceImageFromPlatformDisk() *schema.Resource {
return &schema.Resource{
SchemaVersion: 2,
CreateContext: resourceImageFromPlatformDiskCreate,
ReadContext: resourceImageFromPlatformDiskRead,
UpdateContext: resourceImageFromPlatformDiskUpdate,
DeleteContext: resourceImageFromPlatformDiskDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout30m,
Read: &constants.Timeout900s,
Update: &constants.Timeout900s,
Delete: &constants.Timeout900s,
Default: &constants.Timeout900s,
},
Schema: resourceImageFromPlatformDiskSchemaMake(),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageFromBlankDiskSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}
func resourceImageFromPlatformDiskSchemaMake() map[string]*schema.Schema {
return map[string]*schema.Schema{
"disk_id": {
Type: schema.TypeInt,
Required: true,
Description: "Disk Id",
},
"name": {
Type: schema.TypeString,
Required: true,
Description: "Name of the rescue disk",
},
"boot_type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"bios", "uefi"}, true),
Description: "Boot type of image BIOS or UEFI",
},
"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{"linux", "windows", "unknown"}, true),
Description: "Image type linux, windows or unknown",
},
"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",
},
"sep_id": {
Type: schema.TypeInt,
Computed: true,
Description: "storage endpoint provider ID",
},
"pool_name": {
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "pool for image create",
},
"bootable": {
Type: schema.TypeBool,
Optional: true,
Default: true,
Description: "bootable image",
},
"hot_resize": {
Type: schema.TypeBool,
Optional: true,
Computed: true,
Description: "Does this machine supports hot resize",
},
"async_mode": {
Type: schema.TypeBool,
Optional: true,
Default: false,
Description: "create an image in async/sync mode",
},
"architecture": {
Type: schema.TypeString,
Computed: true,
},
"image_id": {
Type: schema.TypeInt,
Computed: true,
},
"unc_path": {
Type: schema.TypeString,
Computed: true,
},
"ckey": {
Type: schema.TypeString,
Computed: true,
},
"acl": {
Type: schema.TypeString,
Computed: true,
},
"compute_ci_id": {
Type: schema.TypeInt,
Computed: true,
},
"cd_presented_to": {
Type: schema.TypeString,
Computed: true,
},
"deleted_time": {
Type: schema.TypeInt,
Computed: true,
},
"desc": {
Type: schema.TypeString,
Computed: true,
},
"drivers": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"gid": {
Type: schema.TypeInt,
Computed: true,
},
"guid": {
Type: schema.TypeInt,
Computed: true,
},
"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,
},
},
},
},
"last_modified": {
Type: schema.TypeInt,
Computed: true,
},
"link_to": {
Type: schema.TypeInt,
Computed: true,
},
"links_to": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"milestones": {
Type: schema.TypeInt,
Computed: true,
},
"image_name": {
Type: schema.TypeString,
Computed: true,
},
"network_interface_naming": {
Type: schema.TypeString,
Computed: true,
},
"provider_name": {
Type: schema.TypeString,
Computed: true,
},
"purge_attempts": {
Type: schema.TypeInt,
Computed: true,
},
"present_to": {
Type: schema.TypeMap,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"res_id": {
Type: schema.TypeString,
Computed: true,
},
"rescuecd": {
Type: schema.TypeBool,
Computed: true,
},
"shared_with": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{
Type: schema.TypeInt,
},
},
"size": {
Type: schema.TypeInt,
Computed: true,
},
"snapshot_id": {
Type: schema.TypeString,
Computed: true,
},
"status": {
Type: schema.TypeString,
Computed: true,
},
"tech_status": {
Type: schema.TypeString,
Computed: true,
},
"to_clean": {
Type: schema.TypeBool,
Computed: true,
},
"version": {
Type: schema.TypeString,
Computed: true,
},
}
}

View File

@@ -0,0 +1,139 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/constants"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func resourceImageVirtualCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageVirtualCreate: called for image %s", d.Get("name").(string))
c := m.(*controller.ControllerCfg)
req := image.CreateVirtualRequest{
Name: d.Get("name").(string),
TargetID: uint64(d.Get("link_to").(int)),
AccountID: uint64(d.Get("account_id").(int)),
}
imageId, err := c.CloudAPI().Image().CreateVirtual(ctx, req)
if err != nil {
return diag.FromErr(err)
}
d.SetId(strconv.FormatUint(imageId, 10))
d.Set("image_id", imageId)
_, err = utilityImageCheckPresence(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
return resourceImageRead(ctx, d, m)
}
func resourceImageVirtualUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
log.Debugf("resourceImageUpdate: called for %s, id: %s", d.Get("name").(string), d.Id())
if d.HasChange("name") {
err := resourceImageRename(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
}
if d.HasChange("link_to") {
err := resourceImageVirtualLink(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
}
return resourceImageRead(ctx, d, m)
}
func resourceImageVirtualLink(ctx context.Context, d *schema.ResourceData, m interface{}) error {
log.Debugf("resourceVirtualImageLink: called for %s, id: %s", d.Get("name").(string), d.Id())
c := m.(*controller.ControllerCfg)
req := image.LinkRequest{
ImageID: uint64(d.Get("image_id").(int)),
TargetID: uint64(d.Get("link_to").(int)),
}
_, err := c.CloudAPI().Image().Link(ctx, req)
if err != nil {
return err
}
return nil
}
func ResourceImageVirtual() *schema.Resource {
return &schema.Resource{
SchemaVersion: 2,
CreateContext: resourceImageVirtualCreate,
ReadContext: resourceImageRead,
UpdateContext: resourceImageVirtualUpdate,
DeleteContext: resourceImageDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Timeouts: &schema.ResourceTimeout{
Create: &constants.Timeout600s,
Read: &constants.Timeout300s,
Update: &constants.Timeout300s,
Delete: &constants.Timeout300s,
Default: &constants.Timeout300s,
},
Schema: resourceImageVirtualSchemaMake(dataSourceImageExtendSchemaMake()),
StateUpgraders: []schema.StateUpgrader{
{
Type: resourceImageVirtualSchemaV1().CoreConfigSchema().ImpliedType(),
Upgrade: resourcePresentToUpgradeV1,
Version: 1,
},
},
}
}

View File

@@ -0,0 +1,14 @@
package image
import (
"context"
log "github.com/sirupsen/logrus"
)
func resourcePresentToUpgradeV1(ctx context.Context, rawState map[string]interface{}, meta any) (map[string]interface{}, error) {
log.Debug("resourcePresentToUpgradeV1: upgrading state")
rawState["present_to"] = make(map[string]uint64)
return rawState, nil
}

View File

@@ -0,0 +1,65 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
)
func utilityImageCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*image.RecordImage, error) {
c := m.(*controller.ControllerCfg)
req := image.GetRequest{}
if (strconv.Itoa(d.Get("image_id").(int))) != "0" {
req.ImageID = uint64(d.Get("image_id").(int))
} else {
id, _ := strconv.ParseUint(d.Id(), 10, 64)
req.ImageID = id
}
if showAll, ok := d.GetOk("show_all"); ok {
req.ShowAll = showAll.(bool)
}
image, err := c.CloudAPI().Image().Get(ctx, req)
if err != nil {
return nil, err
}
return image, nil
}

View File

@@ -0,0 +1,119 @@
/*
Copyright (c) 2019-2022 Digital Energy Cloud Solutions LLC. All Rights Reserved.
Authors:
Petr Krutov, <petr.krutov@digitalenergy.online>
Stanislav Solovev, <spsolovev@digitalenergy.online>
Kasim Baybikov, <kmbaybikov@basistech.ru>
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.
*/
/*
Terraform DECORT provider - manage resources provided by DECORT (Digital Energy Cloud
Orchestration Technology) with Terraform by Hashicorp.
Source code: https://repository.basistech.ru/BASIS/terraform-provider-decort
Please see README.md to learn where to place source code so that it
builds seamlessly.
Documentation: https://repository.basistech.ru/BASIS/terraform-provider-decort/wiki
*/
package image
import (
"context"
log "github.com/sirupsen/logrus"
"repository.basistech.ru/BASIS/decort-golang-sdk/pkg/cloudapi/image"
"repository.basistech.ru/BASIS/terraform-provider-decort/internal/controller"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
func utilityImageListCheckPresence(ctx context.Context, d *schema.ResourceData, m interface{}) (*image.ListImages, error) {
c := m.(*controller.ControllerCfg)
req := image.ListRequest{}
if sepID, ok := d.GetOk("sep_id"); ok {
req.SEPID = uint64(sepID.(int))
}
if byID, ok := d.GetOk("by_id"); ok {
req.ByID = uint64(byID.(int))
}
if name, ok := d.GetOk("name"); ok {
req.Name = name.(string)
}
if status, ok := d.GetOk("status"); ok {
req.Status = status.(string)
}
if typeImage, ok := d.GetOk("type_image"); ok {
for _, v := range typeImage.([]interface{}) {
req.TypeImage = append(req.TypeImage, v.(string))
}
}
if imageSize, ok := d.GetOk("image_size"); ok {
req.ImageSize = uint64(imageSize.(int))
}
if sepName, ok := d.GetOk("sep_name"); ok {
req.SEPName = sepName.(string)
}
if pool, ok := d.GetOk("pool"); ok {
req.Pool = pool.(string)
}
if public, ok := d.GetOkExists("public"); ok {
req.Public = public.(bool)
}
if hotResize, ok := d.GetOkExists("hot_resize"); ok {
req.HotResize = hotResize.(bool)
}
if bootable, ok := d.GetOkExists("bootable"); ok {
req.Bootable = bootable.(bool)
}
if sortBy, ok := d.GetOk("sort_by"); ok {
req.SortBy = sortBy.(string)
}
if page, ok := d.GetOk("page"); ok {
req.Page = uint64(page.(int))
}
if size, ok := d.GetOk("size"); ok {
req.Size = uint64(size.(int))
}
if enabled, ok := d.GetOkExists("enabled"); ok {
req.Enabled = enabled.(bool)
}
if storagePolicyID, ok := d.GetOk("storage_policy_id"); ok {
req.StoragePolicyID = uint64(storagePolicyID.(int))
}
log.Debugf("utilityImageListCheckPresence: load image list")
imageList, err := c.CloudAPI().Image().List(ctx, req)
if err != nil {
return nil, err
}
return imageList, nil
}