github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/cloudstack/builder.go (about) 1 package cloudstack 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/packer/common" 7 "github.com/hashicorp/packer/helper/communicator" 8 "github.com/hashicorp/packer/helper/multistep" 9 "github.com/hashicorp/packer/packer" 10 "github.com/xanzy/go-cloudstack/cloudstack" 11 ) 12 13 const BuilderId = "packer.cloudstack" 14 15 // Builder represents the CloudStack builder. 16 type Builder struct { 17 config *Config 18 runner multistep.Runner 19 ui packer.Ui 20 } 21 22 // Prepare implements the packer.Builder interface. 23 func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { 24 config, errs := NewConfig(raws...) 25 if errs != nil { 26 return nil, errs 27 } 28 b.config = config 29 30 return nil, nil 31 } 32 33 // Run implements the packer.Builder interface. 34 func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { 35 b.ui = ui 36 37 // Create a CloudStack API client. 38 client := cloudstack.NewAsyncClient( 39 b.config.APIURL, 40 b.config.APIKey, 41 b.config.SecretKey, 42 !b.config.SSLNoVerify, 43 ) 44 45 // Set the time to wait before timing out 46 client.AsyncTimeout(int64(b.config.AsyncTimeout.Seconds())) 47 48 // Some CloudStack service providers only allow HTTP GET calls. 49 client.HTTPGETOnly = b.config.HTTPGetOnly 50 51 // Set up the state. 52 state := new(multistep.BasicStateBag) 53 state.Put("client", client) 54 state.Put("config", b.config) 55 state.Put("hook", hook) 56 state.Put("ui", ui) 57 58 // Build the steps. 59 steps := []multistep.Step{ 60 &stepPrepareConfig{}, 61 &common.StepHTTPServer{ 62 HTTPDir: b.config.HTTPDir, 63 HTTPPortMin: b.config.HTTPPortMin, 64 HTTPPortMax: b.config.HTTPPortMax, 65 }, 66 &stepKeypair{ 67 Debug: b.config.PackerDebug, 68 DebugKeyPath: fmt.Sprintf("cs_%s.pem", b.config.PackerBuildName), 69 KeyPair: b.config.Keypair, 70 PrivateKeyFile: b.config.Comm.SSHPrivateKey, 71 SSHAgentAuth: b.config.Comm.SSHAgentAuth, 72 TemporaryKeyPairName: b.config.TemporaryKeypairName, 73 }, 74 &stepCreateSecurityGroup{}, 75 &stepCreateInstance{ 76 Ctx: b.config.ctx, 77 Debug: b.config.PackerDebug, 78 }, 79 &stepSetupNetworking{}, 80 &communicator.StepConnect{ 81 Config: &b.config.Comm, 82 Host: commHost, 83 SSHConfig: sshConfig( 84 b.config.Comm.SSHAgentAuth, 85 b.config.Comm.SSHUsername, 86 b.config.Comm.SSHPassword), 87 SSHPort: commPort, 88 WinRMPort: commPort, 89 }, 90 &common.StepProvision{}, 91 &stepShutdownInstance{}, 92 &stepCreateTemplate{}, 93 } 94 95 // Configure the runner and run the steps. 96 b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) 97 b.runner.Run(state) 98 99 // If there was an error, return that 100 if rawErr, ok := state.GetOk("error"); ok { 101 ui.Error(rawErr.(error).Error()) 102 return nil, rawErr.(error) 103 } 104 105 // If there was no template created, just return 106 if _, ok := state.GetOk("template"); !ok { 107 return nil, nil 108 } 109 110 // Build the artifact and return it 111 artifact := &Artifact{ 112 client: client, 113 config: b.config, 114 template: state.Get("template").(*cloudstack.CreateTemplateResponse), 115 } 116 117 return artifact, nil 118 } 119 120 // Cancel the step runner. 121 func (b *Builder) Cancel() { 122 if b.runner != nil { 123 b.ui.Say("Cancelling the step runner...") 124 b.runner.Cancel() 125 } 126 }