2016-03-04 05:14:55 -05:00
|
|
|
package arm
|
|
|
|
|
|
|
|
import (
|
2018-01-22 18:32:33 -05:00
|
|
|
"context"
|
2017-11-09 06:20:09 -05:00
|
|
|
"errors"
|
2016-03-04 05:14:55 -05:00
|
|
|
"fmt"
|
|
|
|
|
2018-04-06 04:12:58 -04:00
|
|
|
"github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-02-01/resources"
|
2020-12-17 16:29:25 -05:00
|
|
|
"github.com/hashicorp/packer-plugin-sdk/multistep"
|
|
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
2017-04-04 16:39:01 -04:00
|
|
|
"github.com/hashicorp/packer/builder/azure/common/constants"
|
2016-03-04 05:14:55 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
type StepCreateResourceGroup struct {
|
|
|
|
client *AzureClient
|
2018-04-06 04:12:58 -04:00
|
|
|
create func(ctx context.Context, resourceGroupName string, location string, tags map[string]*string) error
|
2016-03-04 05:14:55 -05:00
|
|
|
say func(message string)
|
|
|
|
error func(e error)
|
2018-04-06 04:12:58 -04:00
|
|
|
exists func(ctx context.Context, resourceGroupName string) (bool, error)
|
2016-03-04 05:14:55 -05:00
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
func NewStepCreateResourceGroup(client *AzureClient, ui packersdk.Ui) *StepCreateResourceGroup {
|
2016-03-04 05:14:55 -05:00
|
|
|
var step = &StepCreateResourceGroup{
|
|
|
|
client: client,
|
|
|
|
say: func(message string) { ui.Say(message) },
|
|
|
|
error: func(e error) { ui.Error(e.Error()) },
|
|
|
|
}
|
|
|
|
|
|
|
|
step.create = step.createResourceGroup
|
2017-11-06 00:16:58 -05:00
|
|
|
step.exists = step.doesResourceGroupExist
|
2016-03-04 05:14:55 -05:00
|
|
|
return step
|
|
|
|
}
|
|
|
|
|
2018-04-06 04:12:58 -04:00
|
|
|
func (s *StepCreateResourceGroup) createResourceGroup(ctx context.Context, resourceGroupName string, location string, tags map[string]*string) error {
|
|
|
|
_, err := s.client.GroupsClient.CreateOrUpdate(ctx, resourceGroupName, resources.Group{
|
2016-03-04 05:14:55 -05:00
|
|
|
Location: &location,
|
2016-07-29 17:17:33 -04:00
|
|
|
Tags: tags,
|
2016-03-04 05:14:55 -05:00
|
|
|
})
|
|
|
|
|
2017-06-08 20:57:59 -04:00
|
|
|
if err != nil {
|
|
|
|
s.say(s.client.LastError.Error())
|
|
|
|
}
|
2016-03-04 05:14:55 -05:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2018-04-06 04:12:58 -04:00
|
|
|
func (s *StepCreateResourceGroup) doesResourceGroupExist(ctx context.Context, resourceGroupName string) (bool, error) {
|
|
|
|
exists, err := s.client.GroupsClient.CheckExistence(ctx, resourceGroupName)
|
2017-11-06 00:16:58 -05:00
|
|
|
if err != nil {
|
|
|
|
s.say(s.client.LastError.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return exists.Response.StatusCode != 404, err
|
|
|
|
}
|
|
|
|
|
2018-04-06 04:12:58 -04:00
|
|
|
func (s *StepCreateResourceGroup) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
2017-11-09 06:20:09 -05:00
|
|
|
var doubleResource, ok = state.GetOk(constants.ArmDoubleResourceGroupNameSet)
|
|
|
|
if ok && doubleResource.(bool) {
|
|
|
|
err := errors.New("You have filled in both temp_resource_group_name and build_resource_group_name. Please choose one.")
|
|
|
|
return processStepResult(err, s.error, state)
|
|
|
|
}
|
2016-03-04 05:14:55 -05:00
|
|
|
|
|
|
|
var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string)
|
|
|
|
var location = state.Get(constants.ArmLocation).(string)
|
2020-09-30 09:55:46 -04:00
|
|
|
tags, ok := state.Get(constants.ArmTags).(map[string]*string)
|
|
|
|
if !ok {
|
|
|
|
err := fmt.Errorf("failed to extract tags from state bag")
|
|
|
|
state.Put(constants.Error, err)
|
|
|
|
s.error(err)
|
|
|
|
return multistep.ActionHalt
|
|
|
|
}
|
2016-03-04 05:14:55 -05:00
|
|
|
|
2018-04-06 04:12:58 -04:00
|
|
|
exists, err := s.exists(ctx, resourceGroupName)
|
2017-11-06 00:16:58 -05:00
|
|
|
if err != nil {
|
2017-11-09 06:20:09 -05:00
|
|
|
return processStepResult(err, s.error, state)
|
2017-11-06 00:16:58 -05:00
|
|
|
}
|
2017-11-09 06:20:09 -05:00
|
|
|
configThinksExists := state.Get(constants.ArmIsExistingResourceGroup).(bool)
|
|
|
|
if exists != configThinksExists {
|
|
|
|
if configThinksExists {
|
|
|
|
err = errors.New("The resource group you want to use does not exist yet. Please use temp_resource_group_name to create a temporary resource group.")
|
|
|
|
} else {
|
|
|
|
err = errors.New("A resource group with that name already exists. Please use build_resource_group_name to use an existing resource group.")
|
|
|
|
}
|
|
|
|
return processStepResult(err, s.error, state)
|
|
|
|
}
|
|
|
|
|
2017-11-06 00:16:58 -05:00
|
|
|
// If the resource group exists, we may not have permissions to update it so we don't.
|
|
|
|
if !exists {
|
2017-11-09 06:20:09 -05:00
|
|
|
s.say("Creating resource group ...")
|
|
|
|
|
|
|
|
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
|
|
|
|
s.say(fmt.Sprintf(" -> Location : '%s'", location))
|
|
|
|
s.say(fmt.Sprintf(" -> Tags :"))
|
2018-04-06 04:12:58 -04:00
|
|
|
for k, v := range tags {
|
2017-11-09 06:20:09 -05:00
|
|
|
s.say(fmt.Sprintf(" ->> %s : %s", k, *v))
|
|
|
|
}
|
2018-04-06 04:12:58 -04:00
|
|
|
err = s.create(ctx, resourceGroupName, location, tags)
|
2017-11-06 00:16:58 -05:00
|
|
|
if err == nil {
|
|
|
|
state.Put(constants.ArmIsResourceGroupCreated, true)
|
|
|
|
}
|
|
|
|
} else {
|
2017-11-09 06:20:09 -05:00
|
|
|
s.say("Using existing resource group ...")
|
|
|
|
s.say(fmt.Sprintf(" -> ResourceGroupName : '%s'", resourceGroupName))
|
|
|
|
s.say(fmt.Sprintf(" -> Location : '%s'", location))
|
2016-04-21 19:50:03 -04:00
|
|
|
state.Put(constants.ArmIsResourceGroupCreated, true)
|
2016-03-04 05:14:55 -05:00
|
|
|
}
|
|
|
|
|
2016-04-21 19:50:03 -04:00
|
|
|
return processStepResult(err, s.error, state)
|
2016-03-04 05:14:55 -05:00
|
|
|
}
|
|
|
|
|
2016-04-21 19:50:03 -04:00
|
|
|
func (s *StepCreateResourceGroup) Cleanup(state multistep.StateBag) {
|
2016-05-09 17:19:55 -04:00
|
|
|
isCreated, ok := state.GetOk(constants.ArmIsResourceGroupCreated)
|
|
|
|
if !ok || !isCreated.(bool) {
|
2016-04-21 19:50:03 -04:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-19 14:54:31 -05:00
|
|
|
ui := state.Get("ui").(packersdk.Ui)
|
2017-11-06 00:16:58 -05:00
|
|
|
if state.Get(constants.ArmIsExistingResourceGroup).(bool) {
|
|
|
|
ui.Say("\nThe resource group was not created by Packer, not deleting ...")
|
|
|
|
return
|
2020-08-10 12:57:06 -04:00
|
|
|
}
|
2016-04-21 19:50:03 -04:00
|
|
|
|
2020-08-10 12:57:06 -04:00
|
|
|
ctx := context.TODO()
|
|
|
|
resourceGroupName := state.Get(constants.ArmResourceGroupName).(string)
|
|
|
|
if exists, err := s.exists(ctx, resourceGroupName); !exists || err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ui.Say("\nCleanup requested, deleting resource group ...")
|
|
|
|
f, err := s.client.GroupsClient.Delete(ctx, resourceGroupName)
|
|
|
|
if err == nil {
|
|
|
|
if state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
|
|
|
|
s.say(fmt.Sprintf("\n Not waiting for Resource Group delete as requested by user. Resource Group Name is %s", resourceGroupName))
|
|
|
|
} else {
|
|
|
|
err = f.WaitForCompletionRef(ctx, s.client.GroupsClient.Client)
|
2017-11-06 00:16:58 -05:00
|
|
|
}
|
|
|
|
}
|
2020-08-10 12:57:06 -04:00
|
|
|
if err != nil {
|
|
|
|
ui.Error(fmt.Sprintf("Error deleting resource group. Please delete it manually.\n\n"+
|
|
|
|
"Name: %s\n"+
|
|
|
|
"Error: %s", resourceGroupName, err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !state.Get(constants.ArmAsyncResourceGroupDelete).(bool) {
|
|
|
|
ui.Say("Resource group has been deleted.")
|
|
|
|
}
|
2016-03-04 05:14:55 -05:00
|
|
|
}
|