Merge pull request #5175 from rickard-von-essen/cloudstack-sg
cloudstack: Add support for Security Groups
This commit is contained in:
commit
4884efd0d4
|
@ -71,6 +71,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
SSHAgentAuth: b.config.Comm.SSHAgentAuth,
|
||||
TemporaryKeyPairName: b.config.TemporaryKeypairName,
|
||||
},
|
||||
&stepCreateSecurityGroup{},
|
||||
&stepCreateInstance{
|
||||
Ctx: b.config.ctx,
|
||||
Debug: b.config.PackerDebug,
|
||||
|
|
|
@ -28,22 +28,24 @@ type Config struct {
|
|||
SSLNoVerify bool `mapstructure:"ssl_no_verify"`
|
||||
|
||||
CIDRList []string `mapstructure:"cidr_list"`
|
||||
CreateSecurityGroup bool `mapstructure:"create_security_group"`
|
||||
DiskOffering string `mapstructure:"disk_offering"`
|
||||
DiskSize int64 `mapstructure:"disk_size"`
|
||||
Expunge bool `mapstructure:"expunge"`
|
||||
Hypervisor string `mapstructure:"hypervisor"`
|
||||
InstanceName string `mapstructure:"instance_name"`
|
||||
Keypair string `mapstructure:"keypair"`
|
||||
TemporaryKeypairName string `mapstructure:"temporary_keypair_name"`
|
||||
Network string `mapstructure:"network"`
|
||||
Project string `mapstructure:"project"`
|
||||
PublicIPAddress string `mapstructure:"public_ip_address"`
|
||||
SecurityGroups []string `mapstructure:"security_groups"`
|
||||
ServiceOffering string `mapstructure:"service_offering"`
|
||||
SourceTemplate string `mapstructure:"source_template"`
|
||||
SourceISO string `mapstructure:"source_iso"`
|
||||
SourceTemplate string `mapstructure:"source_template"`
|
||||
TemporaryKeypairName string `mapstructure:"temporary_keypair_name"`
|
||||
UseLocalIPAddress bool `mapstructure:"use_local_ip_address"`
|
||||
UserData string `mapstructure:"user_data"`
|
||||
UserDataFile string `mapstructure:"user_data_file"`
|
||||
UseLocalIPAddress bool `mapstructure:"use_local_ip_address"`
|
||||
Zone string `mapstructure:"zone"`
|
||||
|
||||
TemplateName string `mapstructure:"template_name"`
|
||||
|
@ -99,7 +101,7 @@ func NewConfig(raws ...interface{}) (*Config, error) {
|
|||
c.AsyncTimeout = 30 * time.Minute
|
||||
}
|
||||
|
||||
if len(c.CIDRList) == 0 && !c.UseLocalIPAddress {
|
||||
if len(c.CIDRList) == 0 {
|
||||
c.CIDRList = []string{"0.0.0.0/0"}
|
||||
}
|
||||
|
||||
|
@ -146,6 +148,10 @@ func NewConfig(raws ...interface{}) (*Config, error) {
|
|||
errs = packer.MultiErrorAppend(errs, errors.New("a network must be specified"))
|
||||
}
|
||||
|
||||
if c.CreateSecurityGroup && !c.Expunge {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("auto creating a temporary security group requires expunge"))
|
||||
}
|
||||
|
||||
if c.ServiceOffering == "" {
|
||||
errs = packer.MultiErrorAppend(errs, errors.New("a service_offering must be specified"))
|
||||
}
|
||||
|
|
|
@ -49,6 +49,10 @@ func (s *stepCreateInstance) Run(state multistep.StateBag) multistep.StepAction
|
|||
p.SetKeypair(keypair.(string))
|
||||
}
|
||||
|
||||
if securitygroups, ok := state.GetOk("security_groups"); ok {
|
||||
p.SetSecuritygroupids(securitygroups.([]string))
|
||||
}
|
||||
|
||||
// If we use an ISO, configure the disk offering.
|
||||
if config.SourceISO != "" {
|
||||
p.SetDiskofferingid(config.DiskOffering)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
package cloudstack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/mitchellh/multistep"
|
||||
"github.com/xanzy/go-cloudstack/cloudstack"
|
||||
)
|
||||
|
||||
type stepCreateSecurityGroup struct {
|
||||
tempSG string
|
||||
}
|
||||
|
||||
func (s *stepCreateSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
|
||||
client := state.Get("client").(*cloudstack.CloudStackClient)
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if len(config.SecurityGroups) > 0 {
|
||||
state.Put("security_groups", config.SecurityGroups)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if !config.CreateSecurityGroup {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
ui.Say("Creating temporary Security Group...")
|
||||
|
||||
p := client.SecurityGroup.NewCreateSecurityGroupParams(
|
||||
fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID()),
|
||||
)
|
||||
p.SetDescription("Temporary SG created by Packer")
|
||||
if config.Project != "" {
|
||||
p.SetProjectid(config.Project)
|
||||
}
|
||||
|
||||
sg, err := client.SecurityGroup.CreateSecurityGroup(p)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Failed to create security group: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.tempSG = sg.Id
|
||||
state.Put("security_groups", []string{sg.Id})
|
||||
|
||||
// Create Ingress rule
|
||||
i := client.SecurityGroup.NewAuthorizeSecurityGroupIngressParams()
|
||||
i.SetCidrlist(config.CIDRList)
|
||||
i.SetProtocol("TCP")
|
||||
i.SetSecuritygroupid(sg.Id)
|
||||
i.SetStartport(config.Comm.Port())
|
||||
i.SetEndport(config.Comm.Port())
|
||||
if config.Project != "" {
|
||||
i.SetProjectid(config.Project)
|
||||
}
|
||||
|
||||
_, err = client.SecurityGroup.AuthorizeSecurityGroupIngress(i)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Failed to authorize security group ingress rule: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
// Cleanup any resources that may have been created during the Run phase.
|
||||
func (s *stepCreateSecurityGroup) Cleanup(state multistep.StateBag) {
|
||||
client := state.Get("client").(*cloudstack.CloudStackClient)
|
||||
config := state.Get("config").(*Config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
if s.tempSG == "" {
|
||||
return
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Cleanup temporary security group: %s ...", s.tempSG))
|
||||
p := client.SecurityGroup.NewDeleteSecurityGroupParams()
|
||||
p.SetId(s.tempSG)
|
||||
if config.Project != "" {
|
||||
p.SetProjectid(config.Project)
|
||||
}
|
||||
|
||||
if _, err := client.SecurityGroup.DeleteSecurityGroup(p); err != nil {
|
||||
ui.Error(err.Error())
|
||||
ui.Error(fmt.Sprintf("Error deleting security group: %s. Please destroy it manually.\n", s.tempSG))
|
||||
}
|
||||
}
|
|
@ -83,6 +83,18 @@ func (s *stepPrepareConfig) Run(state multistep.StateBag) multistep.StepAction {
|
|||
}
|
||||
}
|
||||
|
||||
// Then try to get the SG's UUID's.
|
||||
if len(config.SecurityGroups) > 0 {
|
||||
for i := range config.SecurityGroups {
|
||||
if !isUUID(config.SecurityGroups[i]) {
|
||||
config.SecurityGroups[i], _, err = client.SecurityGroup.GetSecurityGroupID(config.SecurityGroups[i], cloudstack.WithProject(config.Project))
|
||||
if err != nil {
|
||||
errs = packer.MultiErrorAppend(errs, &retrieveErr{"network", config.SecurityGroups[i], err})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !isUUID(config.ServiceOffering) {
|
||||
config.ServiceOffering, _, err = client.ServiceOffering.GetServiceOfferingID(config.ServiceOffering)
|
||||
if err != nil {
|
||||
|
|
|
@ -74,6 +74,11 @@ builder.
|
|||
connect to the instance. Defaults to `[ "0.0.0.0/0" ]`. Only required
|
||||
when `use_local_ip_address` is `false`.
|
||||
|
||||
- `create_security_group` (boolean) - If `true` a temporary security group
|
||||
will be created which allows traffic towards the instance from the
|
||||
`cidr_list`. This option will be ignored if `security_groups` is also
|
||||
defined. Requires `expunge` set to `true`. Defaults to `false`.
|
||||
|
||||
- `disk_offering` (string) - The name or ID of the disk offering used for the
|
||||
instance. This option is only available (and also required) when using
|
||||
`source_iso`.
|
||||
|
@ -118,6 +123,9 @@ builder.
|
|||
connecting any provisioners to. If not provided, a temporary public IP
|
||||
address will be associated and released during the Packer run.
|
||||
|
||||
- `security_groups` (array of strings) - A list of security group IDs or names
|
||||
to associate the instance with.
|
||||
|
||||
- `ssh_agent_auth` (boolean) - If true, the local SSH agent will be used to
|
||||
authenticate connections to the source instance. No temporary keypair will
|
||||
be created, and the values of `ssh_password` and `ssh_private_key_file` will
|
||||
|
|
Loading…
Reference in New Issue