diff --git a/builder/azure/arm/builder.go b/builder/azure/arm/builder.go index 1bd63f426..55e889fe6 100644 --- a/builder/azure/arm/builder.go +++ b/builder/azure/arm/builder.go @@ -238,7 +238,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack NewStepDeployTemplate(azureClient, ui, &b.config, keyVaultDeploymentName, GetKeyVaultDeployment), ) } else { - steps = append(steps, NewStepCertificateInKeyVault(azureClient, ui, &b.config)) + steps = append(steps, NewStepCertificateInKeyVault(&azureClient.VaultClient, ui, &b.config)) } steps = append(steps, NewStepGetCertificate(azureClient, ui), diff --git a/builder/azure/arm/step_certificate_in_keyvault.go b/builder/azure/arm/step_certificate_in_keyvault.go index a46b160ce..d646acead 100644 --- a/builder/azure/arm/step_certificate_in_keyvault.go +++ b/builder/azure/arm/step_certificate_in_keyvault.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/hashicorp/packer/builder/azure/common" "github.com/hashicorp/packer/builder/azure/common/constants" "github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/packer" @@ -11,12 +12,12 @@ import ( type StepCertificateInKeyVault struct { config *Config - client *AzureClient + client common.AZVaultClientIface say func(message string) error func(e error) } -func NewStepCertificateInKeyVault(cli *AzureClient, ui packer.Ui, config *Config) *StepCertificateInKeyVault { +func NewStepCertificateInKeyVault(cli common.AZVaultClientIface, ui packer.Ui, config *Config) *StepCertificateInKeyVault { var step = &StepCertificateInKeyVault{ client: cli, config: config, @@ -29,13 +30,7 @@ func NewStepCertificateInKeyVault(cli *AzureClient, ui packer.Ui, config *Config func (s *StepCertificateInKeyVault) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { s.say("Setting the certificate in the KeyVault...") - var keyVaultName = state.Get(constants.ArmKeyVaultName).(string) - // err := s.client.CreateKey(keyVaultName, DefaultSecretName) - // if err != nil { - // s.error(fmt.Errorf("Error setting winrm cert in custom keyvault: %s", err)) - // return multistep.ActionHalt - // } err := s.client.SetSecret(keyVaultName, DefaultSecretName, s.config.winrmCertificate) if err != nil { diff --git a/builder/azure/arm/step_certificate_in_keyvault_test.go b/builder/azure/arm/step_certificate_in_keyvault_test.go new file mode 100644 index 000000000..a246a7746 --- /dev/null +++ b/builder/azure/arm/step_certificate_in_keyvault_test.go @@ -0,0 +1,66 @@ +package arm + +import ( + "bytes" + "context" + "testing" + + azcommon "github.com/hashicorp/packer/builder/azure/common" + "github.com/hashicorp/packer/builder/azure/common/constants" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +func TestNewStepCertificateInKeyVault(t *testing.T) { + cli := azcommon.MockAZVaultClient{} + ui := &packer.BasicUi{ + Reader: new(bytes.Buffer), + Writer: new(bytes.Buffer), + } + state := new(multistep.BasicStateBag) + state.Put(constants.ArmKeyVaultName, "testKeyVaultName") + + config := &Config{ + winrmCertificate: "testCertificateString", + } + + certKVStep := NewStepCertificateInKeyVault(&cli, ui, config) + stepAction := certKVStep.Run(context.TODO(), state) + + if stepAction == multistep.ActionHalt { + t.Fatalf("step should have succeeded.") + } + if !cli.SetSecretCalled { + t.Fatalf("Step should have called SetSecret on Azure client.") + } + if cli.SetSecretCert != "testCertificateString" { + t.Fatalf("Step should have read cert from winRMCertificate field on config.") + } + if cli.SetSecretVaultName != "testKeyVaultName" { + t.Fatalf("step should have read keyvault name from state.") + } +} + +func TestNewStepCertificateInKeyVault_error(t *testing.T) { + // Tell mock to return an error + cli := azcommon.MockAZVaultClient{} + cli.IsError = true + + ui := &packer.BasicUi{ + Reader: new(bytes.Buffer), + Writer: new(bytes.Buffer), + } + state := new(multistep.BasicStateBag) + state.Put(constants.ArmKeyVaultName, "testKeyVaultName") + + config := &Config{ + winrmCertificate: "testCertificateString", + } + + certKVStep := NewStepCertificateInKeyVault(&cli, ui, config) + stepAction := certKVStep.Run(context.TODO(), state) + + if stepAction != multistep.ActionHalt { + t.Fatalf("step should have failed.") + } +} diff --git a/builder/azure/arm/step_deploy_template.go b/builder/azure/arm/step_deploy_template.go index 15d19394f..a8626bd00 100644 --- a/builder/azure/arm/step_deploy_template.go +++ b/builder/azure/arm/step_deploy_template.go @@ -76,10 +76,6 @@ func (s *StepDeployTemplate) deleteTemplate(ctx context.Context, state multistep } func (s *StepDeployTemplate) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - if s.config.BuildKeyVaultName != "" { - // Deployment already exists - - } s.say("Deploying deployment template ...") var resourceGroupName = state.Get(constants.ArmResourceGroupName).(string) diff --git a/builder/azure/common/vault.go b/builder/azure/common/vault.go index 3c53c0074..2be3e8a36 100644 --- a/builder/azure/common/vault.go +++ b/builder/azure/common/vault.go @@ -16,6 +16,15 @@ const ( AzureVaultApiVersion = "2016-10-01" ) +// Enables us to test steps that access this cli +type AZVaultClientIface interface { + GetSecret(string, string) (*Secret, error) + SetSecret(string, string, string) error + DeletePreparer(string, string) (*http.Request, error) + DeleteResponder(*http.Response) (autorest.Response, error) + DeleteSender(*http.Request) (*http.Response, error) +} + type VaultClient struct { autorest.Client keyVaultEndpoint url.URL diff --git a/builder/azure/common/vault_client_mock.go b/builder/azure/common/vault_client_mock.go new file mode 100644 index 000000000..57bbd1c11 --- /dev/null +++ b/builder/azure/common/vault_client_mock.go @@ -0,0 +1,56 @@ +package common + +import ( + "fmt" + "net/http" + + "github.com/Azure/go-autorest/autorest" +) + +type MockAZVaultClient struct { + GetSecretCalled bool + SetSecretCalled bool + SetSecretVaultName string + SetSecretSecretName string + SetSecretCert string + DeleteResponderCalled bool + DeletePreparerCalled bool + DeleteSenderCalled bool + + IsError bool +} + +func (m *MockAZVaultClient) GetSecret(vaultName, secretName string) (*Secret, error) { + m.GetSecretCalled = true + var secret Secret + return &secret, nil +} + +func (m *MockAZVaultClient) SetSecret(vaultName, secretName string, secretValue string) error { + m.SetSecretCalled = true + m.SetSecretVaultName = vaultName + m.SetSecretSecretName = secretName + m.SetSecretCert = secretValue + + if m.IsError { + return fmt.Errorf("generic error!!") + } + + return nil +} + +func (m *MockAZVaultClient) DeletePreparer(resourceGroupName string, vaultName string) (*http.Request, error) { + m.DeletePreparerCalled = true + return nil, nil +} + +func (m *MockAZVaultClient) DeleteResponder(resp *http.Response) (autorest.Response, error) { + m.DeleteResponderCalled = true + var result autorest.Response + return result, nil +} + +func (m *MockAZVaultClient) DeleteSender(req *http.Request) (*http.Response, error) { + m.DeleteSenderCalled = true + return nil, nil +}