Sharing info with post-processors via artifact (#8632)
This commit is contained in:
parent
f5c58c8e83
commit
dc31bad539
|
@ -20,7 +20,7 @@ type Artifact struct {
|
|||
// BuilderId is the unique ID for the builder that created this AMI
|
||||
BuilderIdValue string
|
||||
|
||||
// SateData should store data such as GeneratedData
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
|
||||
|
|
|
@ -80,4 +80,11 @@ func TestArtifactState(t *testing.T) {
|
|||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ type Artifact struct {
|
|||
// BuilderId is the unique ID for the builder that created this AMI
|
||||
BuilderIdValue string
|
||||
|
||||
// SateData should store data such as GeneratedData
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
|
||||
|
|
|
@ -19,4 +19,11 @@ func TestArtifactState(t *testing.T) {
|
|||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,13 @@ type Artifact struct {
|
|||
|
||||
// Additional Disks
|
||||
AdditionalDisks *[]AdditionalDiskArtifact
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix string) (*Artifact, error) {
|
||||
func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix string, generatedData map[string]interface{}) (*Artifact, error) {
|
||||
return &Artifact{
|
||||
ManagedImageResourceGroupName: resourceGroup,
|
||||
ManagedImageName: name,
|
||||
|
@ -51,10 +55,11 @@ func NewManagedImageArtifact(osType, resourceGroup, name, location, id, osDiskSn
|
|||
OSType: osType,
|
||||
ManagedImageOSDiskSnapshotName: osDiskSnapshotName,
|
||||
ManagedImageDataDiskSnapshotPrefix: dataDiskSnapshotPrefix,
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewManagedImageArtifactWithSIGAsDestination(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix, destinationSharedImageGalleryId string) (*Artifact, error) {
|
||||
func NewManagedImageArtifactWithSIGAsDestination(osType, resourceGroup, name, location, id, osDiskSnapshotName, dataDiskSnapshotPrefix, destinationSharedImageGalleryId string, generatedData map[string]interface{}) (*Artifact, error) {
|
||||
return &Artifact{
|
||||
ManagedImageResourceGroupName: resourceGroup,
|
||||
ManagedImageName: name,
|
||||
|
@ -64,10 +69,11 @@ func NewManagedImageArtifactWithSIGAsDestination(osType, resourceGroup, name, lo
|
|||
ManagedImageOSDiskSnapshotName: osDiskSnapshotName,
|
||||
ManagedImageDataDiskSnapshotPrefix: dataDiskSnapshotPrefix,
|
||||
ManagedImageSharedImageGalleryId: destinationSharedImageGalleryId,
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewArtifact(template *CaptureTemplate, getSasUrl func(name string) string, osType string) (*Artifact, error) {
|
||||
func NewArtifact(template *CaptureTemplate, getSasUrl func(name string) string, osType string, generatedData map[string]interface{}) (*Artifact, error) {
|
||||
if template == nil {
|
||||
return nil, fmt.Errorf("nil capture template")
|
||||
}
|
||||
|
@ -110,6 +116,8 @@ func NewArtifact(template *CaptureTemplate, getSasUrl func(name string) string,
|
|||
AdditionalDisks: additional_disks,
|
||||
|
||||
StorageAccountLocation: template.Resources[0].Location,
|
||||
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -159,6 +167,10 @@ func (a *Artifact) Id() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "atlas.artifact.metadata":
|
||||
return a.stateAtlasMetadata()
|
||||
|
|
|
@ -10,6 +10,10 @@ func getFakeSasUrl(name string) string {
|
|||
return fmt.Sprintf("SAS-%s", name)
|
||||
}
|
||||
|
||||
func generatedData() map[string]interface{} {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
|
||||
func TestArtifactIdVHD(t *testing.T) {
|
||||
template := CaptureTemplate{
|
||||
Resources: []CaptureResources{
|
||||
|
@ -28,7 +32,7 @@ func TestArtifactIdVHD(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -42,7 +46,7 @@ func TestArtifactIdVHD(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactIDManagedImage(t *testing.T) {
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix")
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -65,7 +69,7 @@ ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix
|
|||
}
|
||||
|
||||
func TestArtifactIDManagedImageWithoutOSDiskSnapshotName(t *testing.T) {
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "", "fakeDataDiskSnapshotPrefix")
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "", "fakeDataDiskSnapshotPrefix", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -87,7 +91,7 @@ ManagedImageDataDiskSnapshotPrefix: fakeDataDiskSnapshotPrefix
|
|||
}
|
||||
|
||||
func TestArtifactIDManagedImageWithoutDataDiskSnapshotPrefix(t *testing.T) {
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "")
|
||||
artifact, err := NewManagedImageArtifact("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -109,7 +113,7 @@ ManagedImageOSDiskSnapshotName: fakeOsDiskSnapshotName
|
|||
}
|
||||
|
||||
func TestArtifactIDManagedImageWithSharedImageGalleryId(t *testing.T) {
|
||||
artifact, err := NewManagedImageArtifactWithSIGAsDestination("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix", "fakeSharedImageGallery")
|
||||
artifact, err := NewManagedImageArtifactWithSIGAsDestination("Linux", "fakeResourceGroup", "fakeName", "fakeLocation", "fakeID", "fakeOsDiskSnapshotName", "fakeDataDiskSnapshotPrefix", "fakeSharedImageGallery", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -150,7 +154,7 @@ func TestArtifactString(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -201,7 +205,7 @@ func TestAdditionalDiskArtifactString(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
artifact, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -251,7 +255,7 @@ func TestArtifactProperties(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -301,7 +305,7 @@ func TestAdditionalDiskArtifactProperties(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -356,7 +360,7 @@ func TestArtifactOverHyphenatedCaptureUri(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
testSubject, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err != nil {
|
||||
t.Fatalf("err=%s", err)
|
||||
}
|
||||
|
@ -369,7 +373,7 @@ func TestArtifactOverHyphenatedCaptureUri(t *testing.T) {
|
|||
func TestArtifactRejectMalformedTemplates(t *testing.T) {
|
||||
template := CaptureTemplate{}
|
||||
|
||||
_, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
_, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err == nil {
|
||||
t.Fatalf("Expected artifact creation to fail, but it succeeded.")
|
||||
}
|
||||
|
@ -392,8 +396,34 @@ func TestArtifactRejectMalformedStorageUri(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
_, err := NewArtifact(&template, getFakeSasUrl, "Linux")
|
||||
_, err := NewArtifact(&template, getFakeSasUrl, "Linux", generatedData())
|
||||
if err == nil {
|
||||
t.Fatalf("Expected artifact creation to fail, but it succeeded.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,13 +289,29 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
generatedData := map[string]interface{}{"generated_data": b.stateBag.Get("generated_data")}
|
||||
if b.config.isManagedImage() {
|
||||
managedImageID := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/images/%s",
|
||||
b.config.ClientConfig.SubscriptionID, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName)
|
||||
if b.config.SharedGalleryDestination.SigDestinationGalleryName != "" {
|
||||
return NewManagedImageArtifactWithSIGAsDestination(b.config.OSType, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName, b.config.manageImageLocation, managedImageID, b.config.ManagedImageOSDiskSnapshotName, b.config.ManagedImageDataDiskSnapshotPrefix, b.stateBag.Get(constants.ArmManagedImageSharedGalleryId).(string))
|
||||
return NewManagedImageArtifactWithSIGAsDestination(b.config.OSType,
|
||||
b.config.ManagedImageResourceGroupName,
|
||||
b.config.ManagedImageName,
|
||||
b.config.manageImageLocation,
|
||||
managedImageID,
|
||||
b.config.ManagedImageOSDiskSnapshotName,
|
||||
b.config.ManagedImageDataDiskSnapshotPrefix,
|
||||
b.stateBag.Get(constants.ArmManagedImageSharedGalleryId).(string),
|
||||
generatedData)
|
||||
}
|
||||
return NewManagedImageArtifact(b.config.OSType, b.config.ManagedImageResourceGroupName, b.config.ManagedImageName, b.config.manageImageLocation, managedImageID, b.config.ManagedImageOSDiskSnapshotName, b.config.ManagedImageDataDiskSnapshotPrefix)
|
||||
return NewManagedImageArtifact(b.config.OSType,
|
||||
b.config.ManagedImageResourceGroupName,
|
||||
b.config.ManagedImageName,
|
||||
b.config.manageImageLocation,
|
||||
managedImageID,
|
||||
b.config.ManagedImageOSDiskSnapshotName,
|
||||
b.config.ManagedImageDataDiskSnapshotPrefix,
|
||||
generatedData)
|
||||
} else if template, ok := b.stateBag.GetOk(constants.ArmCaptureTemplate); ok {
|
||||
return NewArtifact(
|
||||
template.(*CaptureTemplate),
|
||||
|
@ -307,10 +323,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
sasUrl, _ := blob.GetSASURI(options)
|
||||
return sasUrl
|
||||
},
|
||||
b.config.OSType)
|
||||
b.config.OSType,
|
||||
generatedData)
|
||||
}
|
||||
|
||||
return &Artifact{}, nil
|
||||
return &Artifact{
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Builder) writeSSHPrivateKey(ui packer.Ui, debugKeyPath string) {
|
||||
|
|
|
@ -448,6 +448,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
artifact := &azcommon.Artifact{
|
||||
Resources: []string{b.config.ImageResourceID},
|
||||
BuilderIdValue: BuilderId,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -22,6 +22,10 @@ type Artifact struct {
|
|||
|
||||
// Azure client for performing API stuff.
|
||||
AzureClientSet client.AzureClientSet
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -54,10 +58,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
switch name {
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -13,6 +13,10 @@ type Artifact struct {
|
|||
client *cloudstack.CloudStackClient
|
||||
config *Config
|
||||
template *cloudstack.CreateTemplateResponse
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// BuilderId returns the builder ID.
|
||||
|
@ -60,5 +64,5 @@ func (a *Artifact) String() string {
|
|||
|
||||
// State returns specific details from the artifact.
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
|
|
@ -45,3 +45,29 @@ func TestArtifactString(t *testing.T) {
|
|||
t.Fatalf("artifact string should match: %s", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,9 +109,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
// Build the artifact and return it
|
||||
artifact := &Artifact{
|
||||
client: client,
|
||||
config: &b.config,
|
||||
template: state.Get("template").(*cloudstack.CreateTemplateResponse),
|
||||
client: client,
|
||||
config: &b.config,
|
||||
template: state.Get("template").(*cloudstack.CreateTemplateResponse),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -22,6 +22,10 @@ type Artifact struct {
|
|||
|
||||
// The client for making API calls
|
||||
Client *godo.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -42,7 +46,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
func generatedData() map[string]interface{} {
|
||||
return make(map[string]interface{})
|
||||
}
|
||||
|
||||
func TestArtifact_Impl(t *testing.T) {
|
||||
var raw interface{}
|
||||
raw = &Artifact{}
|
||||
|
@ -15,7 +19,7 @@ func TestArtifact_Impl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo", "tor1"}, nil}
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo", "tor1"}, nil, generatedData()}
|
||||
expected := "sfo,tor1:42"
|
||||
|
||||
if a.Id() != expected {
|
||||
|
@ -24,7 +28,7 @@ func TestArtifactId(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactIdWithoutMultipleRegions(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo"}, nil}
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo"}, nil, generatedData()}
|
||||
expected := "sfo:42"
|
||||
|
||||
if a.Id() != expected {
|
||||
|
@ -33,7 +37,7 @@ func TestArtifactIdWithoutMultipleRegions(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactString(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo", "tor1"}, nil}
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo", "tor1"}, nil, generatedData()}
|
||||
expected := "A snapshot was created: 'packer-foobar' (ID: 42) in regions 'sfo,tor1'"
|
||||
|
||||
if a.String() != expected {
|
||||
|
@ -42,10 +46,36 @@ func TestArtifactString(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactStringWithoutMultipleRegions(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo"}, nil}
|
||||
a := &Artifact{"packer-foobar", 42, []string{"sfo"}, nil, generatedData()}
|
||||
expected := "A snapshot was created: 'packer-foobar' (ID: 42) in regions 'sfo'"
|
||||
|
||||
if a.String() != expected {
|
||||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,6 +121,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
SnapshotId: state.Get("snapshot_image_id").(int),
|
||||
RegionNames: state.Get("regions").([]string),
|
||||
Client: client,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -9,6 +9,9 @@ import (
|
|||
// exported from docker into a single flat file.
|
||||
type ExportArtifact struct {
|
||||
path string
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*ExportArtifact) BuilderId() string {
|
||||
|
@ -28,7 +31,7 @@ func (a *ExportArtifact) String() string {
|
|||
}
|
||||
|
||||
func (a *ExportArtifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *ExportArtifact) Destroy() error {
|
||||
|
|
|
@ -10,6 +10,10 @@ type ImportArtifact struct {
|
|||
BuilderIdValue string
|
||||
Driver Driver
|
||||
IdValue string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *ImportArtifact) BuilderId() string {
|
||||
|
@ -28,8 +32,8 @@ func (a *ImportArtifact) String() string {
|
|||
return fmt.Sprintf("Imported Docker image: %s", a.Id())
|
||||
}
|
||||
|
||||
func (*ImportArtifact) State(name string) interface{} {
|
||||
return nil
|
||||
func (a *ImportArtifact) State(name string) interface{} {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *ImportArtifact) Destroy() error {
|
||||
|
|
|
@ -105,9 +105,13 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
IdValue: state.Get("image_id").(string),
|
||||
BuilderIdValue: BuilderIdImport,
|
||||
Driver: driver,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
} else {
|
||||
artifact = &ExportArtifact{path: b.config.ExportPath}
|
||||
artifact = &ExportArtifact{
|
||||
path: b.config.ExportPath,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -10,6 +10,9 @@ type Artifact struct {
|
|||
image *Image
|
||||
driver Driver
|
||||
config *Config
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// BuilderId returns the builder Id.
|
||||
|
@ -40,6 +43,10 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "ImageName":
|
||||
return a.image.Name
|
||||
|
|
|
@ -9,3 +9,29 @@ import (
|
|||
func TestArtifact_impl(t *testing.T) {
|
||||
var _ packer.Artifact = new(Artifact)
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,9 +96,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
artifact := &Artifact{
|
||||
image: state.Get("image").(*Image),
|
||||
driver: driver,
|
||||
config: &b.config,
|
||||
image: state.Get("image").(*Image),
|
||||
driver: driver,
|
||||
config: &b.config,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
package googlecompute
|
|
@ -18,6 +18,10 @@ type Artifact struct {
|
|||
|
||||
// The hcloudClient for making API calls
|
||||
hcloudClient *hcloud.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -37,7 +41,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -11,7 +11,8 @@ func TestArtifact_Impl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"packer-foobar", 42, nil, generatedData}
|
||||
expected := "42"
|
||||
|
||||
if a.Id() != expected {
|
||||
|
@ -20,10 +21,37 @@ func TestArtifactId(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactString(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar", 42, nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"packer-foobar", 42, nil, generatedData}
|
||||
expected := "A snapshot was created: 'packer-foobar' (ID: 42)"
|
||||
|
||||
if a.String() != expected {
|
||||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
snapshotName: state.Get("snapshot_name").(string),
|
||||
snapshotId: state.Get("snapshot_id").(int),
|
||||
hcloudClient: b.hcloudClient,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -11,6 +11,10 @@ type Artifact struct {
|
|||
imageName string
|
||||
imageID string
|
||||
client *openapi.APIClient
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -30,7 +34,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -108,6 +108,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
imageID: state.Get("image_id").(string),
|
||||
imageName: state.Get("image_name").(string),
|
||||
client: b.client,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -16,11 +16,15 @@ const BuilderId = "MSOpenTech.hyperv"
|
|||
type artifact struct {
|
||||
dir string
|
||||
f []string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// NewArtifact returns a hyperv artifact containing the files
|
||||
// in the given directory.
|
||||
func NewArtifact(dir string) (packer.Artifact, error) {
|
||||
func NewArtifact(dir string, generatedData map[string]interface{}) (packer.Artifact, error) {
|
||||
files := make([]string, 0, 5)
|
||||
visit := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -38,8 +42,9 @@ func NewArtifact(dir string) (packer.Artifact, error) {
|
|||
}
|
||||
|
||||
return &artifact{
|
||||
dir: dir,
|
||||
f: files,
|
||||
dir: dir,
|
||||
f: files,
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -60,7 +65,7 @@ func (a *artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *artifact) Destroy() error {
|
||||
|
|
|
@ -29,7 +29,8 @@ func TestNewArtifact(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
a, err := NewArtifact(td)
|
||||
generatedData := map[string]interface{}{"generated_data": "data"}
|
||||
a, err := NewArtifact(td, generatedData)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -40,4 +41,7 @@ func TestNewArtifact(t *testing.T) {
|
|||
if len(a.Files()) != 1 {
|
||||
t.Fatalf("should length 1: %d", len(a.Files()))
|
||||
}
|
||||
if a.State("generated_data") != "data" {
|
||||
t.Fatalf("bad: should length have generated_data: %s", a.State("generated_data"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -340,8 +340,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
if _, ok := state.GetOk(multistep.StateHalted); ok {
|
||||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return hypervcommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return hypervcommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
||||
// Cancel.
|
||||
|
|
|
@ -381,7 +381,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return hypervcommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return hypervcommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
||||
// Cancel.
|
||||
|
|
|
@ -9,6 +9,10 @@ import (
|
|||
type Artifact struct {
|
||||
ImageId string
|
||||
RegionID string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -35,7 +39,7 @@ func (a *Artifact) String() string {
|
|||
// Plan
|
||||
// State and destroy function is abandoned
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -88,8 +88,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
artifact := &Artifact{
|
||||
ImageId: b.config.ArtifactId,
|
||||
RegionID: b.config.RegionId,
|
||||
ImageId: b.config.ArtifactId,
|
||||
RegionID: b.config.RegionId,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -13,6 +13,10 @@ type Artifact struct {
|
|||
ImageLabel string
|
||||
|
||||
Driver *linodego.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a Artifact) BuilderId() string { return BuilderID }
|
||||
|
@ -23,7 +27,9 @@ func (a Artifact) String() string {
|
|||
return fmt.Sprintf("Linode image: %s (%s)", a.ImageLabel, a.ImageID)
|
||||
}
|
||||
|
||||
func (a Artifact) State(name string) interface{} { return nil }
|
||||
func (a Artifact) State(name string) interface{} {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a Artifact) Destroy() error {
|
||||
log.Printf("Destroying image: %s (%s)", a.ImageID, a.ImageLabel)
|
||||
|
|
|
@ -15,7 +15,8 @@ func TestArtifact_Impl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
a := &Artifact{"private/42", "packer-foobar", nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"private/42", "packer-foobar", nil, generatedData}
|
||||
expected := "private/42"
|
||||
|
||||
if a.Id() != expected {
|
||||
|
@ -24,10 +25,37 @@ func TestArtifactId(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactString(t *testing.T) {
|
||||
a := &Artifact{"private/42", "packer-foobar", nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"private/42", "packer-foobar", nil, generatedData}
|
||||
expected := "Linode image: packer-foobar (private/42)"
|
||||
|
||||
if a.String() != expected {
|
||||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (ret
|
|||
ImageLabel: image.Label,
|
||||
ImageID: image.ID,
|
||||
Driver: &client,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -8,6 +8,9 @@ import (
|
|||
type Artifact struct {
|
||||
dir string
|
||||
f []string
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -27,7 +30,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -82,8 +82,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
artifact := &Artifact{
|
||||
dir: b.config.OutputDir,
|
||||
f: files,
|
||||
dir: b.config.OutputDir,
|
||||
f: files,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -2,6 +2,7 @@ package lxc
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -26,9 +27,16 @@ func (s *StepProvision) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
CmdWrapper: wrappedCommand,
|
||||
}
|
||||
|
||||
// Loads hook data from builder's state, if it has been set.
|
||||
hookData := common.PopulateProvisionHookData(state)
|
||||
|
||||
// Update state generated_data with complete hookData
|
||||
// to make them accessible by post-processors
|
||||
state.Put("generated_data", hookData)
|
||||
|
||||
// Provision
|
||||
log.Println("Running the provision hook")
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, nil); err != nil {
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, hookData); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
|
||||
type Artifact struct {
|
||||
id string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -25,7 +29,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -62,7 +62,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
artifact := &Artifact{
|
||||
id: state.Get("imageFingerprint").(string),
|
||||
id: state.Get("imageFingerprint").(string),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -2,6 +2,7 @@ package lxd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -23,9 +24,16 @@ func (s *StepProvision) Run(ctx context.Context, state multistep.StateBag) multi
|
|||
CmdWrapper: wrappedCommand,
|
||||
}
|
||||
|
||||
// Loads hook data from builder's state, if it has been set.
|
||||
hookData := common.PopulateProvisionHookData(state)
|
||||
|
||||
// Update state generated_data with complete hookData
|
||||
// to make them accessible by post-processors
|
||||
state.Put("generated_data", hookData)
|
||||
|
||||
// Provision
|
||||
log.Println("Running the provision hook")
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, nil); err != nil {
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, hookData); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ const BuilderID = "ncloud.server.image"
|
|||
|
||||
type Artifact struct {
|
||||
ServerImage *ncloud.ServerImage
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -38,6 +42,9 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
return a.ServerImage.MemberServerImageStatus
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
// Build the artifact and return it
|
||||
artifact := &Artifact{}
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"generated_data": b.stateBag.Get("generated_data")},
|
||||
}
|
||||
|
||||
if serverImage, ok := b.stateBag.GetOk("memberServerImage"); ok {
|
||||
artifact.ServerImage = serverImage.(*ncloud.ServerImage)
|
||||
|
|
|
@ -7,6 +7,10 @@ import (
|
|||
type Artifact struct {
|
||||
snapshotId string
|
||||
snapshotName string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -29,7 +33,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -69,6 +69,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
artifact := &Artifact{
|
||||
snapshotName: b.config.SnapshotName,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
if id, ok := state.GetOk("snapshot_id"); ok {
|
||||
|
|
|
@ -18,6 +18,10 @@ type Artifact struct {
|
|||
|
||||
// OpenStack connection for performing API stuff.
|
||||
Client *gophercloud.ServiceClient
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -38,7 +42,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -34,3 +34,29 @@ func TestArtifactString(t *testing.T) {
|
|||
t.Fatalf("bad: %s", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -184,6 +184,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
ImageId: state.Get("image").(string),
|
||||
BuilderIdValue: BuilderId,
|
||||
Client: imageClient,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -10,6 +10,10 @@ type Artifact struct {
|
|||
MachineImageName string
|
||||
MachineImageFile string
|
||||
ImageListVersion int
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// BuilderId uniquely identifies the builder.
|
||||
|
@ -36,7 +40,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
// Destroy deletes the custom image associated with the artifact.
|
||||
|
|
|
@ -197,6 +197,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
ImageListVersion: state.Get("image_list_version").(int),
|
||||
MachineImageName: state.Get("machine_image_name").(string),
|
||||
MachineImageFile: state.Get("machine_image_file").(string),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -12,6 +12,10 @@ type Artifact struct {
|
|||
Image core.Image
|
||||
Region string
|
||||
driver Driver
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// BuilderId uniquely identifies the builder.
|
||||
|
@ -44,7 +48,7 @@ func (a *Artifact) String() string {
|
|||
|
||||
// State ...
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
// Destroy deletes the custom image associated with the artifact.
|
||||
|
|
|
@ -13,3 +13,29 @@ func TestArtifactImpl(t *testing.T) {
|
|||
t.Fatalf("Artifact should be artifact")
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,9 +98,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
// Build the artifact and return it
|
||||
artifact := &Artifact{
|
||||
Image: image.(core.Image),
|
||||
Region: region,
|
||||
driver: driver,
|
||||
Image: image.(core.Image),
|
||||
Region: region,
|
||||
driver: driver,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -218,6 +218,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Omis: omis.(map[string]string),
|
||||
BuilderIdValue: BuilderId,
|
||||
Config: clientConfig,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -248,6 +248,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Omis: omis.(map[string]string),
|
||||
BuilderIdValue: BuilderId,
|
||||
Config: clientConfig,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -23,6 +23,10 @@ type Artifact struct {
|
|||
|
||||
// Client connection for performing API stuff.
|
||||
Conn *oapi.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -56,7 +60,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -199,6 +199,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Volumes: state.Get("bsuvolumes").(BsuVolumes),
|
||||
BuilderIdValue: BuilderId,
|
||||
Conn: oapiconn,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
ui.Say(fmt.Sprintf("Created Volumes: %s", artifact))
|
||||
return artifact, nil
|
||||
|
|
|
@ -308,6 +308,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Omis: state.Get("omis").(map[string]string),
|
||||
BuilderIdValue: BuilderId,
|
||||
Config: clientConfig,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -2,6 +2,7 @@ package chroot
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
|
@ -24,9 +25,16 @@ func (s *StepChrootProvision) Run(ctx context.Context, state multistep.StateBag)
|
|||
CmdWrapper: wrappedCommand,
|
||||
}
|
||||
|
||||
// Loads hook data from builder's state, if it has been set.
|
||||
hookData := common.PopulateProvisionHookData(state)
|
||||
|
||||
// Update state generated_data with complete hookData
|
||||
// to make them accessible by post-processors
|
||||
state.Put("generated_data", hookData)
|
||||
|
||||
// Provision
|
||||
log.Println("Running the provision hook")
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, nil); err != nil {
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, hookData); err != nil {
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ type Artifact struct {
|
|||
|
||||
// OAPI connection for performing API stuff.
|
||||
Config *oapi.Config
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -55,6 +59,10 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "atlas.artifact.metadata":
|
||||
return a.stateAtlasMetadata()
|
||||
|
|
|
@ -21,11 +21,15 @@ var unnecessaryFiles = []string{"\\.log$", "\\.backup$", "\\.Backup$", "\\.app"}
|
|||
type artifact struct {
|
||||
dir string
|
||||
f []string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// NewArtifact returns a Parallels artifact containing the files
|
||||
// in the given directory.
|
||||
func NewArtifact(dir string) (packer.Artifact, error) {
|
||||
func NewArtifact(dir string, generatedData map[string]interface{}) (packer.Artifact, error) {
|
||||
files := make([]string, 0, 5)
|
||||
visit := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -57,8 +61,9 @@ func NewArtifact(dir string) (packer.Artifact, error) {
|
|||
}
|
||||
|
||||
return &artifact{
|
||||
dir: dir,
|
||||
f: files,
|
||||
dir: dir,
|
||||
f: files,
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -79,7 +84,7 @@ func (a *artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *artifact) Destroy() error {
|
||||
|
|
|
@ -29,7 +29,8 @@ func TestNewArtifact(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
a, err := NewArtifact(td)
|
||||
generatedData := map[string]interface{}{"generated_data": "data"}
|
||||
a, err := NewArtifact(td, generatedData)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -40,4 +41,7 @@ func TestNewArtifact(t *testing.T) {
|
|||
if len(a.Files()) != 1 {
|
||||
t.Fatalf("should length 1: %d", len(a.Files()))
|
||||
}
|
||||
if a.State("generated_data") != "data" {
|
||||
t.Fatalf("bad: should length have generated_data: %s", a.State("generated_data"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -291,5 +291,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return parallelscommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return parallelscommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
|
|
@ -134,7 +134,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return parallelscommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return parallelscommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
||||
// Cancel.
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
|
||||
type Artifact struct {
|
||||
snapshotData string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -25,7 +29,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -15,10 +15,37 @@ func TestArtifact_Impl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactString(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar"}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"packer-foobar", generatedData}
|
||||
expected := "A snapshot was created: 'packer-foobar'"
|
||||
|
||||
if a.String() != expected {
|
||||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
|
||||
artifact := &Artifact{
|
||||
snapshotData: config.SnapshotName,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ import (
|
|||
type Artifact struct {
|
||||
templateID int
|
||||
proxmoxClient *proxmox.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// Artifact implements packer.Artifact
|
||||
|
@ -34,7 +38,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -118,6 +118,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
artifact := &Artifact{
|
||||
templateID: tplID,
|
||||
proxmoxClient: b.proxmoxClient,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -726,6 +726,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
state: make(map[string]interface{}),
|
||||
}
|
||||
|
||||
artifact.state["generated_data"] = state.Get("generated_data")
|
||||
artifact.state["diskName"] = b.config.VMName
|
||||
diskpaths, ok := state.Get("qemu_disk_paths").([]string)
|
||||
if ok {
|
||||
|
|
|
@ -25,6 +25,10 @@ type Artifact struct {
|
|||
|
||||
// The client for making API calls
|
||||
client *api.ScalewayAPI
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (*Artifact) BuilderId() string {
|
||||
|
@ -46,7 +50,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -15,7 +15,8 @@ func TestArtifact_Impl(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactId(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar-image", "cc586e45-5156-4f71-b223-cf406b10dd1d", "packer-foobar-snapshot", "cc586e45-5156-4f71-b223-cf406b10dd1c", "ams1", nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"packer-foobar-image", "cc586e45-5156-4f71-b223-cf406b10dd1d", "packer-foobar-snapshot", "cc586e45-5156-4f71-b223-cf406b10dd1c", "ams1", nil, generatedData}
|
||||
expected := "ams1:cc586e45-5156-4f71-b223-cf406b10dd1d"
|
||||
|
||||
if a.Id() != expected {
|
||||
|
@ -24,10 +25,37 @@ func TestArtifactId(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestArtifactString(t *testing.T) {
|
||||
a := &Artifact{"packer-foobar-image", "cc586e45-5156-4f71-b223-cf406b10dd1d", "packer-foobar-snapshot", "cc586e45-5156-4f71-b223-cf406b10dd1c", "ams1", nil}
|
||||
generatedData := make(map[string]interface{})
|
||||
a := &Artifact{"packer-foobar-image", "cc586e45-5156-4f71-b223-cf406b10dd1d", "packer-foobar-snapshot", "cc586e45-5156-4f71-b223-cf406b10dd1c", "ams1", nil, generatedData}
|
||||
expected := "An image was created: 'packer-foobar-image' (ID: cc586e45-5156-4f71-b223-cf406b10dd1d) in region 'ams1' based on snapshot 'packer-foobar-snapshot' (ID: cc586e45-5156-4f71-b223-cf406b10dd1c)"
|
||||
|
||||
if a.String() != expected {
|
||||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
snapshotID: state.Get("snapshot_id").(string),
|
||||
regionName: state.Get("region").(string),
|
||||
client: client,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -15,6 +15,10 @@ type Artifact struct {
|
|||
TencentCloudImages map[string]string
|
||||
BuilderIdValue string
|
||||
Client *cvm.Client
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -46,6 +50,10 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "atlas.artifact.metadata":
|
||||
return a.stateAtlasMetadata()
|
||||
|
|
|
@ -154,6 +154,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
TencentCloudImages: state.Get("tencentcloudimages").(map[string]string),
|
||||
BuilderIdValue: BuilderId,
|
||||
Client: cvmClient,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -15,6 +15,10 @@ type Artifact struct {
|
|||
|
||||
// SDC connection for cleanup etc
|
||||
Driver Driver
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -35,7 +39,7 @@ func (a *Artifact) String() string {
|
|||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
//TODO(jen20): Figure out how to make this work with Atlas
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -96,6 +96,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
ImageID: state.Get("image").(string),
|
||||
BuilderIDValue: BuilderId,
|
||||
Driver: driver,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -16,6 +16,10 @@ type Artifact struct {
|
|||
BuilderIdValue string
|
||||
|
||||
Client *UCloudClient
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -48,6 +52,10 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "atlas.artifact.metadata":
|
||||
return a.stateAtlasMetadata()
|
||||
|
|
|
@ -64,3 +64,29 @@ func TestArtifactState_atlasMetadata(t *testing.T) {
|
|||
t.Fatalf("bad: %#v", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState_StateData(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -149,6 +149,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
UCloudImages: state.Get("ucloud_images").(*ucloudcommon.ImageInfoSet),
|
||||
BuilderIdValue: BuilderId,
|
||||
Client: client,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
|
||||
return artifact, nil
|
||||
|
|
|
@ -16,14 +16,19 @@ type artifact struct {
|
|||
OutputDir string
|
||||
BoxName string
|
||||
Provider string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// NewArtifact returns a vagrant artifact containing the .box file
|
||||
func NewArtifact(provider, dir string) packer.Artifact {
|
||||
func NewArtifact(provider, dir string, generatedData map[string]interface{}) packer.Artifact {
|
||||
return &artifact{
|
||||
OutputDir: dir,
|
||||
BoxName: "package.box",
|
||||
Provider: provider,
|
||||
StateData: generatedData,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +49,7 @@ func (a *artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *artifact) Destroy() error {
|
||||
|
|
|
@ -44,3 +44,29 @@ func TestArtifactString(t *testing.T) {
|
|||
t.Fatalf("artifact string should match: expected: %s received: %s", expected, a.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
a := &artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := a.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = a.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
a = &artifact{}
|
||||
result = a.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -323,7 +323,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return NewArtifact(b.config.Provider, b.config.OutputDir), nil
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return NewArtifact(b.config.Provider, b.config.OutputDir, generatedData), nil
|
||||
}
|
||||
|
||||
// Cancel.
|
||||
|
|
|
@ -16,11 +16,15 @@ const BuilderId = "mitchellh.virtualbox"
|
|||
type artifact struct {
|
||||
dir string
|
||||
f []string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
// NewArtifact returns a VirtualBox artifact containing the files
|
||||
// in the given directory.
|
||||
func NewArtifact(dir string) (packer.Artifact, error) {
|
||||
func NewArtifact(dir string, generatedData map[string]interface{}) (packer.Artifact, error) {
|
||||
files := make([]string, 0, 5)
|
||||
visit := func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
|
@ -38,8 +42,9 @@ func NewArtifact(dir string) (packer.Artifact, error) {
|
|||
}
|
||||
|
||||
return &artifact{
|
||||
dir: dir,
|
||||
f: files,
|
||||
dir: dir,
|
||||
f: files,
|
||||
StateData: generatedData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -60,7 +65,7 @@ func (a *artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *artifact) Destroy() error {
|
||||
|
|
|
@ -29,7 +29,8 @@ func TestNewArtifact(t *testing.T) {
|
|||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
a, err := NewArtifact(td)
|
||||
generatedData := map[string]interface{}{"generated_data": "data"}
|
||||
a, err := NewArtifact(td, generatedData)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
@ -40,4 +41,7 @@ func TestNewArtifact(t *testing.T) {
|
|||
if len(a.Files()) != 1 {
|
||||
t.Fatalf("should length 1: %d", len(a.Files()))
|
||||
}
|
||||
if a.State("generated_data") != "data" {
|
||||
t.Fatalf("bad: should length have generated_data: %s", a.State("generated_data"))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -423,5 +423,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
|
|
@ -181,7 +181,8 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, errors.New("Build was halted.")
|
||||
}
|
||||
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
||||
// Cancel.
|
||||
|
|
|
@ -176,5 +176,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir)
|
||||
generatedData := map[string]interface{}{"generated_data": state.Get("generated_data")}
|
||||
return vboxcommon.NewArtifact(b.config.OutputDir, generatedData)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@ type artifact struct {
|
|||
dir OutputDir
|
||||
f []string
|
||||
config map[string]string
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *artifact) BuilderId() string {
|
||||
|
@ -45,6 +49,9 @@ func (a *artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
return a.config[name]
|
||||
}
|
||||
|
||||
|
@ -87,5 +94,6 @@ func NewArtifact(remoteType string, format string, exportOutputPath string, vmNa
|
|||
dir: dir,
|
||||
f: files,
|
||||
config: config,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -92,8 +92,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, nil
|
||||
}
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ const BuilderId = "jetbrains.vsphere"
|
|||
type Artifact struct {
|
||||
Name string
|
||||
VM *driver.VirtualMachine
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
@ -28,7 +32,7 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
|
|
|
@ -141,8 +141,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, nil
|
||||
}
|
||||
artifact := &common.Artifact{
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
Name: b.config.VMName,
|
||||
VM: state.Get("vm").(*driver.VirtualMachine),
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ type Artifact struct {
|
|||
config *Config
|
||||
driver Driver
|
||||
image *compute.Image
|
||||
|
||||
// StateData should store data such as GeneratedData
|
||||
// to be shared with post-processors
|
||||
StateData map[string]interface{}
|
||||
}
|
||||
|
||||
//revive:disable:var-naming
|
||||
|
@ -31,6 +35,10 @@ func (a *Artifact) String() string {
|
|||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
if _, ok := a.StateData[name]; ok {
|
||||
return a.StateData[name]
|
||||
}
|
||||
|
||||
switch name {
|
||||
case "ImageID":
|
||||
return a.image.Id
|
||||
|
|
|
@ -41,3 +41,29 @@ func TestArtifact_String(t *testing.T) {
|
|||
t.Fatalf("artifact string should match: %v", expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestArtifactState(t *testing.T) {
|
||||
expectedData := "this is the data"
|
||||
artifact := &Artifact{
|
||||
StateData: map[string]interface{}{"state_data": expectedData},
|
||||
}
|
||||
|
||||
// Valid state
|
||||
result := artifact.State("state_data")
|
||||
if result != expectedData {
|
||||
t.Fatalf("Bad: State data was %s instead of %s", result, expectedData)
|
||||
}
|
||||
|
||||
// Invalid state
|
||||
result = artifact.State("invalid_key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for invalid state data name")
|
||||
}
|
||||
|
||||
// Nil StateData should not fail and should return nil
|
||||
artifact = &Artifact{}
|
||||
result = artifact.State("key")
|
||||
if result != nil {
|
||||
t.Fatalf("Bad: State should be nil for nil StateData")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,8 +91,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
artifact := &Artifact{
|
||||
image: image.(*compute.Image),
|
||||
config: &b.config,
|
||||
image: image.(*compute.Image),
|
||||
config: &b.config,
|
||||
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
|
||||
}
|
||||
return artifact, nil
|
||||
}
|
||||
|
|
|
@ -28,6 +28,10 @@ func (s *StepChrootProvision) Run(ctx context.Context, state multistep.StateBag)
|
|||
// Loads hook data from builder's state, if it has been set.
|
||||
hookData := common.PopulateProvisionHookData(state)
|
||||
|
||||
// Update state generated_data with complete hookData
|
||||
// to make them accessible by post-processors
|
||||
state.Put("generated_data", hookData)
|
||||
|
||||
// Provision
|
||||
log.Println("Running the provision hook")
|
||||
if err := hook.Run(ctx, packer.HookProvision, ui, comm, hookData); err != nil {
|
||||
|
|
|
@ -36,9 +36,6 @@ func PopulateProvisionHookData(state multistep.StateBag) map[string]interface{}
|
|||
// Implemented in most others including digitalOcean (droplet id),
|
||||
// docker (container_id), and clouds which use "server" internally instead
|
||||
// of instance.
|
||||
|
||||
// Also note that Chroot and lxc/lxd builders tend to have their own custom
|
||||
// step_provision, so they won't use this code path.
|
||||
id, ok := state.GetOk("instance_id")
|
||||
if ok {
|
||||
hookData["ID"] = id
|
||||
|
@ -93,6 +90,10 @@ func (s *StepProvision) runWithHook(ctx context.Context, state multistep.StateBa
|
|||
|
||||
hookData := PopulateProvisionHookData(state)
|
||||
|
||||
// Update state generated_data with complete hookData
|
||||
// to make them accessible by post-processors
|
||||
state.Put("generated_data", hookData)
|
||||
|
||||
// Run the provisioner in a goroutine so we can continually check
|
||||
// for cancellations...
|
||||
if hooktype == packer.HookProvision {
|
||||
|
|
|
@ -135,6 +135,13 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
|
||||
var err error
|
||||
|
||||
generatedData := artifact.State("generated_data")
|
||||
if generatedData == nil {
|
||||
// Make sure it's not a nil map so we can assign to it later.
|
||||
generatedData = make(map[string]interface{})
|
||||
}
|
||||
p.config.ctx.Data = generatedData
|
||||
|
||||
// Render this key since we didn't in the configure phase
|
||||
p.config.OSSKey, err = interpolate.Render(p.config.OSSKey, &p.config.ctx)
|
||||
if err != nil {
|
||||
|
|
|
@ -127,6 +127,13 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
|
||||
var err error
|
||||
|
||||
generatedData := artifact.State("generated_data")
|
||||
if generatedData == nil {
|
||||
// Make sure it's not a nil map so we can assign to it later.
|
||||
generatedData = make(map[string]interface{})
|
||||
}
|
||||
p.config.ctx.Data = generatedData
|
||||
|
||||
session, err := p.config.Session()
|
||||
if err != nil {
|
||||
return nil, false, false, err
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue