feature: bsusurrogate, add security group step
This commit is contained in:
parent
cef9a4b9fd
commit
5ef3e81234
|
@ -158,6 +158,12 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
Comm: &b.config.RunConfig.Comm,
|
||||
DebugKeyPath: fmt.Sprintf("oapi_%s.pem", b.config.PackerBuildName),
|
||||
},
|
||||
&osccommon.StepSecurityGroup{
|
||||
SecurityGroupFilter: b.config.SecurityGroupFilter,
|
||||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
|
||||
},
|
||||
}
|
||||
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
|
|
|
@ -12,19 +12,19 @@ func buildNetFilters(input map[string]string) oapi.FiltersNet {
|
|||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
switch name := k; name {
|
||||
case "ip_range":
|
||||
case "ip-range":
|
||||
filters.IpRanges = filterValue
|
||||
case "dhcp_options_set_id":
|
||||
case "dhcp-options-set-id":
|
||||
filters.DhcpOptionsSetIds = filterValue
|
||||
case "is_default":
|
||||
case "is-default":
|
||||
if isDefault, err := strconv.ParseBool(v); err == nil {
|
||||
filters.IsDefault = isDefault
|
||||
}
|
||||
case "state":
|
||||
filters.States = filterValue
|
||||
case "tag_key":
|
||||
case "tag-key":
|
||||
filters.TagKeys = filterValue
|
||||
case "tag_value":
|
||||
case "tag-value":
|
||||
filters.TagValues = filterValue
|
||||
default:
|
||||
log.Printf("[Debug] Unknown Filter Name: %s.", name)
|
||||
|
@ -38,19 +38,19 @@ func buildSubnetFilters(input map[string]string) oapi.FiltersSubnet {
|
|||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
switch name := k; name {
|
||||
case "available_ips_counts":
|
||||
case "available-ips-counts":
|
||||
if ipCount, err := strconv.Atoi(v); err == nil {
|
||||
filters.AvailableIpsCounts = []int64{int64(ipCount)}
|
||||
}
|
||||
case "ip_ranges":
|
||||
case "ip-ranges":
|
||||
filters.IpRanges = filterValue
|
||||
case "net_ids":
|
||||
case "net-ids":
|
||||
filters.NetIds = filterValue
|
||||
case "states":
|
||||
filters.States = filterValue
|
||||
case "subnet_ids":
|
||||
case "subnet-ids":
|
||||
filters.SubnetIds = filterValue
|
||||
case "sub_region_names":
|
||||
case "sub-region-names":
|
||||
filters.SubregionNames = filterValue
|
||||
default:
|
||||
log.Printf("[Debug] Unknown Filter Name: %s.", name)
|
||||
|
@ -65,23 +65,23 @@ func buildOMIFilters(input map[string]string) oapi.FiltersImage {
|
|||
filterValue := []string{v}
|
||||
|
||||
switch name := k; name {
|
||||
case "account_aliases":
|
||||
case "account-aliases":
|
||||
filters.AccountAliases = filterValue
|
||||
case "account_ids":
|
||||
case "account-ids":
|
||||
filters.AccountIds = filterValue
|
||||
case "architectures":
|
||||
filters.Architectures = filterValue
|
||||
case "image_ids":
|
||||
case "image-ids":
|
||||
filters.ImageIds = filterValue
|
||||
case "image_names":
|
||||
case "image-names":
|
||||
filters.ImageNames = filterValue
|
||||
case "image_types":
|
||||
case "image-types":
|
||||
filters.ImageTypes = filterValue
|
||||
case "virtualization_types":
|
||||
case "virtualization-types":
|
||||
filters.VirtualizationTypes = filterValue
|
||||
case "root_device_types":
|
||||
case "root-device-types":
|
||||
filters.RootDeviceTypes = filterValue
|
||||
case "block_device_mapping_volume_type":
|
||||
case "block-device-mapping-volume-type":
|
||||
filters.BlockDeviceMappingVolumeType = filterValue
|
||||
//Some params are missing.
|
||||
default:
|
||||
|
@ -90,3 +90,68 @@ func buildOMIFilters(input map[string]string) oapi.FiltersImage {
|
|||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
func buildSecurityGroupFilters(input map[string]string) oapi.FiltersSecurityGroup {
|
||||
var filters oapi.FiltersSecurityGroup
|
||||
for k, v := range input {
|
||||
filterValue := []string{v}
|
||||
|
||||
switch name := k; name {
|
||||
case "account-ids":
|
||||
filters.AccountIds = filterValue
|
||||
case "descriptions":
|
||||
filters.Descriptions = filterValue
|
||||
case "inbound-rule-account-ids":
|
||||
filters.InboundRuleAccountIds = filterValue
|
||||
case "inbound-rule-from-port-ranges":
|
||||
if val, err := strconv.Atoi(v); err == nil {
|
||||
filters.InboundRuleFromPortRanges = []int64{int64(val)}
|
||||
}
|
||||
case "inbound-rule-ip-ranges":
|
||||
filters.InboundRuleIpRanges = filterValue
|
||||
case "inbound-rule-protocols":
|
||||
filters.InboundRuleProtocols = filterValue
|
||||
case "inbound-rule-security-group-ids":
|
||||
filters.InboundRuleSecurityGroupIds = filterValue
|
||||
case "inbound-rule-security-group-names":
|
||||
filters.InboundRuleSecurityGroupNames = filterValue
|
||||
case "inbound-rule-to-port-ranges":
|
||||
if val, err := strconv.Atoi(v); err == nil {
|
||||
filters.InboundRuleToPortRanges = []int64{int64(val)}
|
||||
}
|
||||
case "net-ids":
|
||||
filters.NetIds = filterValue
|
||||
|
||||
case "outbound-rule-account-ids":
|
||||
filters.OutboundRuleAccountIds = filterValue
|
||||
case "outbound-rule-from-port-ranges":
|
||||
if val, err := strconv.Atoi(v); err == nil {
|
||||
filters.OutboundRuleFromPortRanges = []int64{int64(val)}
|
||||
}
|
||||
case "outbound-rule-ip-ranges":
|
||||
filters.OutboundRuleIpRanges = filterValue
|
||||
case "outbound-rule-protocols":
|
||||
filters.OutboundRuleProtocols = filterValue
|
||||
case "outbound-rule-security-group-ids":
|
||||
filters.OutboundRuleSecurityGroupIds = filterValue
|
||||
case "outbound-rule-security-group-names":
|
||||
filters.OutboundRuleSecurityGroupNames = filterValue
|
||||
case "outbound-rule-to-port-ranges":
|
||||
if val, err := strconv.Atoi(v); err == nil {
|
||||
filters.OutboundRuleToPortRanges = []int64{int64(val)}
|
||||
}
|
||||
case "security-group-ids":
|
||||
filters.SecurityGroupIds = filterValue
|
||||
case "security-group-names":
|
||||
filters.SecurityGroupNames = filterValue
|
||||
case "tags-keys":
|
||||
filters.TagKeys = filterValue
|
||||
case "tags-values":
|
||||
filters.TagValues = filterValue
|
||||
//Some params are missing.
|
||||
default:
|
||||
log.Printf("[Debug] Unknown Filter Name: %s.", name)
|
||||
}
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ func (d *NetFilterOptions) Empty() bool {
|
|||
}
|
||||
|
||||
type SecurityGroupFilterOptions struct {
|
||||
Filters map[*string]*string
|
||||
Filters map[string]string
|
||||
}
|
||||
|
||||
func (d *SecurityGroupFilterOptions) Empty() bool {
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
type stateRefreshFunc func() (string, error)
|
||||
|
||||
func waitForSecurityGroup(conn *oapi.Client, securityGroupID string) error {
|
||||
errCh := make(chan error, 1)
|
||||
go waitForState(errCh, "exists", securityGroupWaitFunc(conn, securityGroupID))
|
||||
err := <-errCh
|
||||
return err
|
||||
}
|
||||
|
||||
func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) error {
|
||||
err := common.Retry(2, 2, 0, func(_ uint) (bool, error) {
|
||||
state, err := refresh()
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else if state == target {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
errCh <- err
|
||||
return err
|
||||
}
|
||||
|
||||
func securityGroupWaitFunc(conn *oapi.Client, id string) stateRefreshFunc {
|
||||
return func() (string, error) {
|
||||
log.Printf("[Debug] Check if SG with id %s exists", id)
|
||||
resp, err := conn.POST_ReadSecurityGroups(oapi.ReadSecurityGroupsRequest{
|
||||
Filters: oapi.FiltersSecurityGroup{
|
||||
SecurityGroupIds: []string{id},
|
||||
},
|
||||
})
|
||||
|
||||
log.Printf("[Debug] Read Response %+v", resp.OK)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if resp.OK == nil {
|
||||
return "", fmt.Errorf("Security Group with ID %s. Not Found", id)
|
||||
}
|
||||
|
||||
if len(resp.OK.SecurityGroups) == 0 {
|
||||
return "waiting", nil
|
||||
}
|
||||
|
||||
return "exists", nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
type StepSecurityGroup struct {
|
||||
CommConfig *communicator.Config
|
||||
SecurityGroupFilter SecurityGroupFilterOptions
|
||||
SecurityGroupIds []string
|
||||
TemporarySGSourceCidr string
|
||||
|
||||
createdGroupId string
|
||||
}
|
||||
|
||||
func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
oapiconn := state.Get("oapi").(*oapi.Client)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
netId := state.Get("net_id").(string)
|
||||
|
||||
if len(s.SecurityGroupIds) > 0 {
|
||||
resp, err := oapiconn.POST_ReadSecurityGroups(
|
||||
oapi.ReadSecurityGroupsRequest{
|
||||
Filters: oapi.FiltersSecurityGroup{
|
||||
SecurityGroupIds: s.SecurityGroupIds,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil || resp.OK == nil || len(resp.OK.SecurityGroups) <= 0 {
|
||||
err := fmt.Errorf("Couldn't find specified security group: %s", err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
log.Printf("Using specified security groups: %v", s.SecurityGroupIds)
|
||||
state.Put("securityGroupIds", s.SecurityGroupIds)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if !s.SecurityGroupFilter.Empty() {
|
||||
|
||||
params := oapi.ReadSecurityGroupsRequest{}
|
||||
if netId != "" {
|
||||
s.SecurityGroupFilter.Filters["net-id"] = netId
|
||||
}
|
||||
params.Filters = buildSecurityGroupFilters(s.SecurityGroupFilter.Filters)
|
||||
|
||||
log.Printf("Using SecurityGroup Filters %v", params)
|
||||
|
||||
sgResp, err := oapiconn.POST_ReadSecurityGroups(params)
|
||||
if err != nil || sgResp.OK == nil {
|
||||
err := fmt.Errorf("Couldn't find security groups for filter: %s", err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
securityGroupIds := []string{}
|
||||
for _, sg := range sgResp.OK.SecurityGroups {
|
||||
securityGroupIds = append(securityGroupIds, sg.SecurityGroupId)
|
||||
}
|
||||
|
||||
ui.Message(fmt.Sprintf("Found Security Group(s): %s", strings.Join(securityGroupIds, ", ")))
|
||||
state.Put("securityGroupIds", securityGroupIds)
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
port := s.CommConfig.Port()
|
||||
if port == 0 {
|
||||
if s.CommConfig.Type != "none" {
|
||||
panic("port must be set to a non-zero value.")
|
||||
}
|
||||
}
|
||||
|
||||
// Create the group
|
||||
groupName := fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
|
||||
ui.Say(fmt.Sprintf("Creating temporary security group for this instance: %s", groupName))
|
||||
group := oapi.CreateSecurityGroupRequest{
|
||||
SecurityGroupName: groupName,
|
||||
Description: "Temporary group for Packer",
|
||||
}
|
||||
|
||||
group.NetId = netId
|
||||
|
||||
groupResp, err := oapiconn.POST_CreateSecurityGroup(group)
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Set the group ID so we can delete it later
|
||||
s.createdGroupId = groupResp.OK.SecurityGroup.SecurityGroupId
|
||||
|
||||
// Wait for the security group become available for authorizing
|
||||
log.Printf("[DEBUG] Waiting for temporary security group: %s", s.createdGroupId)
|
||||
err = waitForSecurityGroup(oapiconn, s.createdGroupId)
|
||||
if err == nil {
|
||||
log.Printf("[DEBUG] Found security group %s", s.createdGroupId)
|
||||
} else {
|
||||
err := fmt.Errorf("Timed out waiting for security group %s: %s", s.createdGroupId, err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Authorize the SSH access for the security group
|
||||
groupRules := oapi.CreateSecurityGroupRuleRequest{
|
||||
SecurityGroupId: groupResp.OK.SecurityGroup.SecurityGroupId,
|
||||
Flow: "Inbound",
|
||||
Rules: []oapi.SecurityGroupRule{
|
||||
oapi.SecurityGroupRule{
|
||||
FromPortRange: int64(port),
|
||||
ToPortRange: int64(port),
|
||||
IpRanges: []string{s.TemporarySGSourceCidr},
|
||||
IpProtocol: "tcp",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf(
|
||||
"Authorizing access to port %d from %s in the temporary security group...",
|
||||
port, s.TemporarySGSourceCidr))
|
||||
_, err = oapiconn.POST_CreateSecurityGroupRule(groupRules)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error authorizing temporary security group: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
// Set some state data for use in future steps
|
||||
state.Put("securityGroupIds", []string{s.createdGroupId})
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
|
||||
if s.createdGroupId == "" {
|
||||
return
|
||||
}
|
||||
|
||||
oapiconn := state.Get("oapi").(*oapi.Client)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say("Deleting temporary security group...")
|
||||
|
||||
var err error
|
||||
for i := 0; i < 5; i++ {
|
||||
_, err = oapiconn.POST_DeleteSecurityGroup(oapi.DeleteSecurityGroupRequest{SecurityGroupId: s.createdGroupId})
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
|
||||
log.Printf("Error deleting security group: %s", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error cleaning up security group. Please delete the group manually: %s", s.createdGroupId))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue