diff --git a/CHANGELOG.md b/CHANGELOG.md index c560fc532..adbb99e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ file [GH-9379] * post-processor/yandex-import: Support using URL from yandex-export pp [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 lines [GH-9438] diff --git a/post-processor/yandex-import/artifact.go b/post-processor/yandex-import/artifact.go index c1112019a..1efcdb4d3 100644 --- a/post-processor/yandex-import/artifact.go +++ b/post-processor/yandex-import/artifact.go @@ -7,8 +7,8 @@ import ( const BuilderId = "packer.post-processor.yandex-import" type Artifact struct { - imageID string - sourceURL string + imageID string + imageSource string } func (*Artifact) BuilderId() string { @@ -16,7 +16,7 @@ func (*Artifact) BuilderId() string { } func (a *Artifact) Id() string { - return a.sourceURL + return a.imageSource } func (a *Artifact) Files() []string { @@ -24,7 +24,7 @@ func (a *Artifact) Files() []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{} { diff --git a/post-processor/yandex-import/post-processor.go b/post-processor/yandex-import/post-processor.go index 32e5c71c9..525118ca2 100644 --- a/post-processor/yandex-import/post-processor.go +++ b/post-processor/yandex-import/post-processor.go @@ -6,6 +6,7 @@ package yandeximport import ( "context" "fmt" + "net/url" "os" "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) } - var url string + var imageSource string var fileSource bool // 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") } - 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 { return nil, false, false, err } - case yandexexport.BuilderId: + case yandexexport.BuilderId, BuilderId: // 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: - // Artifact from prev yandex-import PP, reuse URL - url = artifact.Id() + case yandex.BuilderID: + // Artifact is plain Yandex Compute Image, just create new one based on provided. + imageSource = artifact.Id() default: err := fmt.Errorf( @@ -218,18 +223,13 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact return nil, false, false, err } - presignedUrl, err := presignUrl(storageClient, ui, url) - 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) + 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 } if fileSource && !p.config.SkipClean { - err = deleteFromBucket(storageClient, ui, url) + err = deleteFromBucket(storageClient, ui, imageSource) if err != nil { return nil, false, false, err } @@ -244,8 +244,8 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact } return &Artifact{ - imageID: ycImage.GetId(), - sourceURL: url, + imageID: ycImage.GetId(), + imageSource: imageSource, }, 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 } -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) { - op, err := driver.SDK().WrapOperation(driver.SDK().Compute().Image().Create(ctx, &compute.CreateImageRequest{ +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) { + req := &compute.CreateImageRequest{ FolderId: folderID, Name: imageName, Description: imageDescription, Labels: imageLabels, 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 { ui.Say("Error creating Yandex Compute Image") 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()))