github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/openstack/builder.go (about) 1 // The openstack package contains a packer.Builder implementation that 2 // builds Images for openstack. 3 4 package openstack 5 6 import ( 7 "fmt" 8 "log" 9 10 "github.com/hashicorp/packer/common" 11 "github.com/hashicorp/packer/helper/communicator" 12 "github.com/hashicorp/packer/helper/config" 13 "github.com/hashicorp/packer/packer" 14 "github.com/hashicorp/packer/template/interpolate" 15 "github.com/mitchellh/multistep" 16 ) 17 18 // The unique ID for this builder 19 const BuilderId = "mitchellh.openstack" 20 21 type Config struct { 22 common.PackerConfig `mapstructure:",squash"` 23 24 AccessConfig `mapstructure:",squash"` 25 ImageConfig `mapstructure:",squash"` 26 RunConfig `mapstructure:",squash"` 27 28 ctx interpolate.Context 29 } 30 31 type Builder struct { 32 config Config 33 runner multistep.Runner 34 } 35 36 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 37 err := config.Decode(&b.config, &config.DecodeOpts{ 38 Interpolate: true, 39 InterpolateContext: &b.config.ctx, 40 }, raws...) 41 if err != nil { 42 return nil, err 43 } 44 45 // Accumulate any errors 46 var errs *packer.MultiError 47 errs = packer.MultiErrorAppend(errs, b.config.AccessConfig.Prepare(&b.config.ctx)...) 48 errs = packer.MultiErrorAppend(errs, b.config.ImageConfig.Prepare(&b.config.ctx)...) 49 errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(&b.config.ctx)...) 50 51 if errs != nil && len(errs.Errors) > 0 { 52 return nil, errs 53 } 54 55 log.Println(common.ScrubConfig(b.config, b.config.Password)) 56 return nil, nil 57 } 58 59 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 60 computeClient, err := b.config.computeV2Client() 61 if err != nil { 62 return nil, fmt.Errorf("Error initializing compute client: %s", err) 63 } 64 65 // Setup the state bag and initial state for the steps 66 state := new(multistep.BasicStateBag) 67 state.Put("config", b.config) 68 state.Put("hook", hook) 69 state.Put("ui", ui) 70 71 // Build the steps 72 steps := []multistep.Step{ 73 &StepLoadExtensions{}, 74 &StepLoadFlavor{ 75 Flavor: b.config.Flavor, 76 }, 77 &StepKeyPair{ 78 Debug: b.config.PackerDebug, 79 DebugKeyPath: fmt.Sprintf("os_%s.pem", b.config.PackerBuildName), 80 KeyPairName: b.config.SSHKeyPairName, 81 TemporaryKeyPairName: b.config.TemporaryKeyPairName, 82 PrivateKeyFile: b.config.RunConfig.Comm.SSHPrivateKey, 83 SSHAgentAuth: b.config.RunConfig.Comm.SSHAgentAuth, 84 }, 85 &StepRunSourceServer{ 86 Name: b.config.ImageName, 87 SourceImage: b.config.SourceImage, 88 SourceImageName: b.config.SourceImageName, 89 SecurityGroups: b.config.SecurityGroups, 90 Networks: b.config.Networks, 91 AvailabilityZone: b.config.AvailabilityZone, 92 UserData: b.config.UserData, 93 UserDataFile: b.config.UserDataFile, 94 ConfigDrive: b.config.ConfigDrive, 95 InstanceMetadata: b.config.InstanceMetadata, 96 }, 97 &StepGetPassword{ 98 Debug: b.config.PackerDebug, 99 Comm: &b.config.RunConfig.Comm, 100 }, 101 &StepWaitForRackConnect{ 102 Wait: b.config.RackconnectWait, 103 }, 104 &StepAllocateIp{ 105 FloatingIpPool: b.config.FloatingIpPool, 106 FloatingIp: b.config.FloatingIp, 107 ReuseIps: b.config.ReuseIps, 108 }, 109 &communicator.StepConnect{ 110 Config: &b.config.RunConfig.Comm, 111 Host: CommHost( 112 computeClient, 113 b.config.SSHInterface, 114 b.config.SSHIPVersion), 115 SSHConfig: SSHConfig( 116 b.config.RunConfig.Comm.SSHAgentAuth, 117 b.config.RunConfig.Comm.SSHUsername, 118 b.config.RunConfig.Comm.SSHPassword), 119 }, 120 &common.StepProvision{}, 121 &StepStopServer{}, 122 &stepCreateImage{}, 123 &stepUpdateImageVisibility{}, 124 &stepAddImageMembers{}, 125 } 126 127 // Run! 128 b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) 129 b.runner.Run(state) 130 131 // If there was an error, return that 132 if rawErr, ok := state.GetOk("error"); ok { 133 return nil, rawErr.(error) 134 } 135 136 // If there are no images, then just return 137 if _, ok := state.GetOk("image"); !ok { 138 return nil, nil 139 } 140 141 // Build the artifact and return it 142 artifact := &Artifact{ 143 ImageId: state.Get("image").(string), 144 BuilderIdValue: BuilderId, 145 Client: computeClient, 146 } 147 148 return artifact, nil 149 } 150 151 func (b *Builder) Cancel() { 152 if b.runner != nil { 153 log.Println("Cancelling the step runner...") 154 b.runner.Cancel() 155 } 156 }