Skip to content

Commit

Permalink
added support for image from volume
Browse files Browse the repository at this point in the history
  • Loading branch information
ujjwal-ibm committed Jun 21, 2021
1 parent 0c41a2e commit a275323
Show file tree
Hide file tree
Showing 9 changed files with 299 additions and 22 deletions.
18 changes: 18 additions & 0 deletions examples/ibm-is-ng/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,24 @@ data "ibm_is_dedicated_host" "dhost" {
host_group = data.ibm_is_dedicated_host_group.dgroup.id
}

resource "ibm_is_image" "image1" {
href = var.image_cos_url
name = "my-img-1"
operating_system = var.image_operating_system
}

resource "ibm_is_image" "image2" {
source_volume = data.ibm_is_instance.instance1.volume_attachments.0.volume_id
name = "my-img-1"
}

data "ibm_is_image" "dsimage" {
name = ibm_is_image.image1.name
}

data "ibm_is_images" "dsimages" {
}

resource "ibm_is_instance_disk_management" "disks"{
instance = ibm_is_instance.instance1.id
disks {
Expand Down
8 changes: 8 additions & 0 deletions examples/ibm-is-ng/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ variable "profile" {
default = "cx2-2x4"
}

variable "image_cos_url" {
default = "cos://us-south/cosbucket-vpc-image-gen2/rhel-guest-image-7.0-encrypted.qcow2"
}

variable "image_operating_system" {
default = "red-7-amd64"
}

8 changes: 8 additions & 0 deletions ibm/data_source_ibm_is_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ func dataSourceIBMISImage() *schema.Resource {
Computed: true,
Description: "The type of encryption used on the image",
},
"source_volume": {
Type: schema.TypeString,
Computed: true,
Description: "Source volume id of the image",
},
},
}
}
Expand Down Expand Up @@ -181,6 +186,9 @@ func imageGet(d *schema.ResourceData, meta interface{}, name, visibility string)
if image.File != nil && image.File.Checksums != nil {
d.Set(isImageCheckSum, *image.File.Checksums.Sha256)
}
if image.SourceVolume != nil {
d.Set("source_volume", *image.SourceVolume.ID)
}
return nil
}
}
Expand Down
8 changes: 8 additions & 0 deletions ibm/data_source_ibm_is_images.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func dataSourceIBMISImages() *schema.Resource {
Computed: true,
Description: "The type of encryption used on the image",
},
"source_volume": {
Type: schema.TypeString,
Computed: true,
Description: "Source volume id of the image",
},
},
},
},
Expand Down Expand Up @@ -188,6 +193,9 @@ func imageList(d *schema.ResourceData, meta interface{}) error {
if image.EncryptionKey != nil {
l["encryption_key"] = *image.EncryptionKey.CRN
}
if image.SourceVolume != nil {
l["source_volume"] = *image.SourceVolume.ID
}
imagesInfo = append(imagesInfo, l)
}
d.SetId(dataSourceIBMISSubnetsID(d))
Expand Down
161 changes: 142 additions & 19 deletions ibm/resource_ibm_is_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const (
isImageStatus = "status"
isImageVisibility = "visibility"
isImageFile = "file"
isImageVolume = "source_volume"
isImageMinimumProvisionedSize = "size"

isImageResourceGroup = "resource_group"
Expand Down Expand Up @@ -62,10 +63,13 @@ func resourceIBMISImage() *schema.Resource {

Schema: map[string]*schema.Schema{
isImageHref: {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: applyOnce,
Description: "Image Href value",
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
RequiredWith: []string{isImageOperatingSystem},
ExactlyOneOf: []string{isImageHref, isImageVolume},
Description: "Image Href value",
},

isImageName: {
Expand Down Expand Up @@ -98,10 +102,12 @@ func resourceIBMISImage() *schema.Resource {
},

isImageOperatingSystem: {
Type: schema.TypeString,
Required: true,
ForceNew: true,
Description: "Image Operating system",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
RequiredWith: []string{isImageHref},
Computed: true,
Description: "Image Operating system",
},

isImageEncryption: {
Expand Down Expand Up @@ -133,6 +139,14 @@ func resourceIBMISImage() *schema.Resource {
Description: "Details for the stored image file",
},

isImageVolume: {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ExactlyOneOf: []string{isImageHref, isImageVolume},
Description: "Image volume id",
},

isImageResourceGroup: {
Type: schema.TypeString,
ForceNew: true,
Expand Down Expand Up @@ -215,16 +229,24 @@ func resourceIBMISImageCreate(d *schema.ResourceData, meta interface{}) error {
href := d.Get(isImageHref).(string)
name := d.Get(isImageName).(string)
operatingSystem := d.Get(isImageOperatingSystem).(string)
volume := d.Get(isImageVolume).(string)

if userDetails.generation == 1 {
err := classicImgCreate(d, meta, href, name, operatingSystem)
if err != nil {
return err
}
} else {
err := imgCreate(d, meta, href, name, operatingSystem)
if err != nil {
return err
if volume != "" {
err := imgCreateByVolume(d, meta, name, volume)
if err != nil {
return err
}
} else {
err := imgCreateByFile(d, meta, href, name, operatingSystem)
if err != nil {
return err
}
}
}
return resourceIBMISImageRead(d, meta)
Expand Down Expand Up @@ -270,18 +292,18 @@ func classicImgCreate(d *schema.ResourceData, meta interface{}, href, name, oper
err = UpdateTagsUsingCRN(oldList, newList, meta, *image.CRN)
if err != nil {
log.Printf(
"Error on create of resource vpc image (%s) tags: %s", d.Id(), err)
"Error on create of resource vpc Image (%s) tags: %s", d.Id(), err)
}
}
return nil
}

func imgCreate(d *schema.ResourceData, meta interface{}, href, name, operatingSystem string) error {
func imgCreateByFile(d *schema.ResourceData, meta interface{}, href, name, operatingSystem string) error {
sess, err := vpcClient(meta)
if err != nil {
return err
}
imagePrototype := &vpcv1.ImagePrototype{
imagePrototype := &vpcv1.ImagePrototypeImageByFile{
Name: &name,
File: &vpcv1.ImageFilePrototype{
Href: &href,
Expand Down Expand Up @@ -310,7 +332,6 @@ func imgCreate(d *schema.ResourceData, meta interface{}, href, name, operatingSy
options := &vpcv1.CreateImageOptions{
ImagePrototype: imagePrototype,
}

image, response, err := sess.CreateImage(options)
if err != nil {
return fmt.Errorf("[DEBUG] Image creation err %s\n%s", err, response)
Expand All @@ -327,7 +348,96 @@ func imgCreate(d *schema.ResourceData, meta interface{}, href, name, operatingSy
err = UpdateTagsUsingCRN(oldList, newList, meta, *image.CRN)
if err != nil {
log.Printf(
"Error on create of resource vpc image (%s) tags: %s", d.Id(), err)
"Error on create of resource vpc Image (%s) tags: %s", d.Id(), err)
}
}
return nil
}
func imgCreateByVolume(d *schema.ResourceData, meta interface{}, name, volume string) error {
sess, err := vpcClient(meta)
if err != nil {
return err
}
imagePrototype := &vpcv1.ImagePrototypeImageBySourceVolume{
Name: &name,
}
var insId string
imagePrototype.SourceVolume = &vpcv1.VolumeIdentity{
ID: &volume,
}
options := &vpcv1.GetVolumeOptions{
ID: &volume,
}
vol, response, err := sess.GetVolume(options)
if err != nil || vol == nil {
return fmt.Errorf("Error retrieving Volume (%s) details: %s\n%s", volume, err, response)
}
if vol.VolumeAttachments == nil {
return fmt.Errorf("Error creating Image because the specified source_volume %s is not attached to a virtual server instance ", volume)
}
volAtt := &vol.VolumeAttachments[0]
insId = *volAtt.Instance.ID
getinsOptions := &vpcv1.GetInstanceOptions{
ID: &insId,
}
instance, response, err := sess.GetInstance(getinsOptions)
if err != nil || instance == nil {
return fmt.Errorf("Error retrieving Instance (%s) to which the source_volume (%s) is attached : %s\n%s", insId, volume, err, response)
}
if instance != nil && *instance.Status == "running" {
actiontype := "stop"
createinsactoptions := &vpcv1.CreateInstanceActionOptions{
InstanceID: &insId,
Type: &actiontype,
}
_, response, err = sess.CreateInstanceAction(createinsactoptions)
if err != nil {
return fmt.Errorf("Error stopping Instance (%s) to which the source_volume (%s) is attached : %s\n%s", insId, volume, err, response)
}
_, err = isWaitForInstanceActionStop(sess, d.Timeout(schema.TimeoutCreate), insId, d)
if err != nil {
return err
}
} else if *instance.Status != "stopped" {
_, err = isWaitForInstanceActionStop(sess, d.Timeout(schema.TimeoutCreate), insId, d)
if err != nil {
return err
}
}

if encryptionKey, ok := d.GetOk(isImageEncryptionKey); ok {
encryptionKeyStr := encryptionKey.(string)
// Construct an instance of the EncryptionKeyReference model
encryptionKeyReferenceModel := new(vpcv1.EncryptionKeyIdentity)
encryptionKeyReferenceModel.CRN = &encryptionKeyStr
imagePrototype.EncryptionKey = encryptionKeyReferenceModel
}
if rgrp, ok := d.GetOk(isImageResourceGroup); ok {
rg := rgrp.(string)
imagePrototype.ResourceGroup = &vpcv1.ResourceGroupIdentity{
ID: &rg,
}
}
imagOptions := &vpcv1.CreateImageOptions{
ImagePrototype: imagePrototype,
}
image, response, err := sess.CreateImage(imagOptions)
if err != nil {
return fmt.Errorf("[DEBUG] Image creation err %s\n%s", err, response)
}
d.SetId(*image.ID)
log.Printf("[INFO] Image ID : %s", *image.ID)
_, err = isWaitForImageAvailable(sess, d.Id(), d.Timeout(schema.TimeoutCreate))
if err != nil {
return err
}
v := os.Getenv("IC_ENV_TAGS")
if _, ok := d.GetOk(isImageTags); ok || v != "" {
oldList, newList := d.GetChange(isImageTags)
err = UpdateTagsUsingCRN(oldList, newList, meta, *image.CRN)
if err != nil {
log.Printf(
"Error on create of resource vpc Image (%s) tags: %s", d.Id(), err)
}
}
return nil
Expand Down Expand Up @@ -379,7 +489,6 @@ func isWaitForImageAvailable(imageC *vpcv1.VpcV1, id string, timeout time.Durati

return stateConf.WaitForState()
}

func isImageRefreshFunc(imageC *vpcv1.VpcV1, id string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
getimgoptions := &vpcv1.GetImageOptions{
Expand Down Expand Up @@ -599,11 +708,25 @@ func imgGet(d *schema.ResourceData, meta interface{}, id string) error {
return fmt.Errorf("Error Getting Image (%s): %s\n%s", id, err, response)
}
// d.Set(isImageArchitecure, image.Architecture)
d.Set(isImageMinimumProvisionedSize, *image.MinimumProvisionedSize)
if image.MinimumProvisionedSize != nil {
d.Set(isImageMinimumProvisionedSize, *image.MinimumProvisionedSize)
}
d.Set(isImageName, *image.Name)
d.Set(isImageOperatingSystem, *image.OperatingSystem.Name)
// d.Set(isImageFormat, image.Format)
d.Set(isImageFile, *image.File.Size)
if image.Encryption != nil {
d.Set("encryption", *image.Encryption)
}
if image.EncryptionKey != nil {
d.Set("encryption_key", *image.EncryptionKey.CRN)
}
if image.File != nil && image.File.Size != nil {
d.Set(isImageFile, *image.File.Size)
}
if image.SourceVolume != nil {
d.Set(isImageVolume, *image.SourceVolume.ID)
}

d.Set(isImageHref, *image.Href)
d.Set(isImageStatus, *image.Status)
d.Set(isImageVisibility, *image.Visibility)
Expand Down
Loading

0 comments on commit a275323

Please sign in to comment.