yandex-import: allow create image based on another one
Allow as source for a new Compute Image not only URL to Storage Object but also a another one Compute Image Details at official doc about ImageCreateRequest https://cloud.yandex.com/docs/compute/grpc/image_service#CreateImageRequest
This commit is contained in:
parent
ea4aa67f78
commit
e0cc7b9d8c
|
@ -67,6 +67,7 @@
|
||||||
file [GH-9379]
|
file [GH-9379]
|
||||||
* post-processor/yandex-import: Support using URL from yandex-export pp
|
* post-processor/yandex-import: Support using URL from yandex-export pp
|
||||||
[GH-9601]
|
[GH-9601]
|
||||||
|
* post-processor/yandex-import: Support create the new Image based on another one
|
||||||
* provisioner/ansible: Add template option for templating the inventory file
|
* provisioner/ansible: Add template option for templating the inventory file
|
||||||
lines [GH-9438]
|
lines [GH-9438]
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ const BuilderId = "packer.post-processor.yandex-import"
|
||||||
|
|
||||||
type Artifact struct {
|
type Artifact struct {
|
||||||
imageID string
|
imageID string
|
||||||
sourceURL string
|
imageSource string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Artifact) BuilderId() string {
|
func (*Artifact) BuilderId() string {
|
||||||
|
@ -16,7 +16,7 @@ func (*Artifact) BuilderId() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Artifact) Id() string {
|
func (a *Artifact) Id() string {
|
||||||
return a.sourceURL
|
return a.imageSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Artifact) Files() []string {
|
func (a *Artifact) Files() []string {
|
||||||
|
@ -24,7 +24,7 @@ func (a *Artifact) Files() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Artifact) String() string {
|
func (a *Artifact) String() string {
|
||||||
return fmt.Sprintf("Create image %v from URL %v", a.imageID, a.sourceURL)
|
return fmt.Sprintf("Create image %v from source URL/image %v", a.imageID, a.imageSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Artifact) State(name string) interface{} {
|
func (*Artifact) State(name string) interface{} {
|
||||||
|
|
|
@ -6,6 +6,7 @@ package yandeximport
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
return nil, false, false, fmt.Errorf("error rendering object_name template: %s", err)
|
return nil, false, false, fmt.Errorf("error rendering object_name template: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var url string
|
var imageSource string
|
||||||
var fileSource bool
|
var fileSource bool
|
||||||
|
|
||||||
// Create temporary storage Access Key
|
// Create temporary storage Access Key
|
||||||
|
@ -198,18 +199,22 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
return nil, false, false, fmt.Errorf("To upload artfact you need to specify `bucket` value")
|
return nil, false, false, fmt.Errorf("To upload artfact you need to specify `bucket` value")
|
||||||
}
|
}
|
||||||
|
|
||||||
url, err = uploadToBucket(storageClient, ui, artifact, p.config.Bucket, p.config.ObjectName)
|
imageSource, err = uploadToBucket(storageClient, ui, artifact, p.config.Bucket, p.config.ObjectName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
case yandexexport.BuilderId:
|
case yandexexport.BuilderId, BuilderId:
|
||||||
// Artifact already in storage, just get URL
|
// Artifact already in storage, just get URL
|
||||||
url = artifact.Id()
|
// OR artifact from prev yandex-import PP, reuse URL
|
||||||
|
imageSource, err = presignUrl(storageClient, ui, artifact.Id())
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, false, err
|
||||||
|
}
|
||||||
|
|
||||||
case BuilderId:
|
case yandex.BuilderID:
|
||||||
// Artifact from prev yandex-import PP, reuse URL
|
// Artifact is plain Yandex Compute Image, just create new one based on provided.
|
||||||
url = artifact.Id()
|
imageSource = artifact.Id()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
|
@ -218,18 +223,13 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
presignedUrl, err := presignUrl(storageClient, ui, url)
|
ycImage, err := createYCImage(ctx, client, ui, p.config.FolderID, imageSource, p.config.ImageName, p.config.ImageDescription, p.config.ImageFamily, p.config.ImageLabels)
|
||||||
if err != nil {
|
|
||||||
return nil, false, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ycImage, err := createYCImage(ctx, client, ui, p.config.FolderID, presignedUrl, p.config.ImageName, p.config.ImageDescription, p.config.ImageFamily, p.config.ImageLabels)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if fileSource && !p.config.SkipClean {
|
if fileSource && !p.config.SkipClean {
|
||||||
err = deleteFromBucket(storageClient, ui, url)
|
err = deleteFromBucket(storageClient, ui, imageSource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, false, err
|
return nil, false, false, err
|
||||||
}
|
}
|
||||||
|
@ -245,7 +245,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
|
||||||
|
|
||||||
return &Artifact{
|
return &Artifact{
|
||||||
imageID: ycImage.GetId(),
|
imageID: ycImage.GetId(),
|
||||||
sourceURL: url,
|
imageSource: imageSource,
|
||||||
}, false, false, nil
|
}, false, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,21 +294,30 @@ func uploadToBucket(s3conn *s3.S3, ui packer.Ui, artifact packer.Artifact, bucke
|
||||||
return req.HTTPRequest.URL.String(), nil
|
return req.HTTPRequest.URL.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createYCImage(ctx context.Context, driver yandex.Driver, ui packer.Ui, folderID string, rawImageURL string, imageName string, imageDescription string, imageFamily string, imageLabels map[string]string) (*compute.Image, error) {
|
func createYCImage(ctx context.Context, driver yandex.Driver, ui packer.Ui, folderID string, imageSource string, imageName string, imageDescription string, imageFamily string, imageLabels map[string]string) (*compute.Image, error) {
|
||||||
op, err := driver.SDK().WrapOperation(driver.SDK().Compute().Image().Create(ctx, &compute.CreateImageRequest{
|
req := &compute.CreateImageRequest{
|
||||||
FolderId: folderID,
|
FolderId: folderID,
|
||||||
Name: imageName,
|
Name: imageName,
|
||||||
Description: imageDescription,
|
Description: imageDescription,
|
||||||
Labels: imageLabels,
|
Labels: imageLabels,
|
||||||
Family: imageFamily,
|
Family: imageFamily,
|
||||||
Source: &compute.CreateImageRequest_Uri{Uri: rawImageURL},
|
}
|
||||||
}))
|
|
||||||
|
// switch on imageSource value: cloud image id or storage URL
|
||||||
|
_, err := url.Parse(imageSource)
|
||||||
|
if err == nil {
|
||||||
|
req.Source = &compute.CreateImageRequest_Uri{Uri: imageSource}
|
||||||
|
} else {
|
||||||
|
req.Source = &compute.CreateImageRequest_ImageId{ImageId: imageSource}
|
||||||
|
}
|
||||||
|
|
||||||
|
op, err := driver.SDK().WrapOperation(driver.SDK().Compute().Image().Create(ctx, req))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say("Error creating Yandex Compute Image")
|
ui.Say("Error creating Yandex Compute Image")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Source url for Image creation: %v", rawImageURL))
|
ui.Say(fmt.Sprintf("Source url for Image creation: %v", imageSource))
|
||||||
|
|
||||||
ui.Say(fmt.Sprintf("Creating Yandex Compute Image %v within operation %#v", imageName, op.Id()))
|
ui.Say(fmt.Sprintf("Creating Yandex Compute Image %v within operation %#v", imageName, op.Id()))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue