func (d Destroy) deleteBOSH(stack cloudformation.Stack, state storage.State) (storage.State, error) {
	emptyBOSH := storage.BOSH{}
	if reflect.DeepEqual(state.BOSH, emptyBOSH) {
		d.logger.Println("no BOSH director, skipping...")
		return state, nil
	}

	if err := d.boshDeleter.Delete(state.BOSH.Manifest, state.BOSH.State, state.KeyPair.PrivateKey); err != nil {
		return state, err
	}

	state.BOSH = storage.BOSH{}

	return state, nil
}
func (u Up) Execute(subcommandFlags []string, state storage.State) error {
	config, err := u.parseFlags(subcommandFlags)
	if err != nil {
		return err
	}

	if u.awsCredentialsPresent(config) {
		state.AWS.AccessKeyID = config.awsAccessKeyID
		state.AWS.SecretAccessKey = config.awsSecretAccessKey
		state.AWS.Region = config.awsRegion
		if err := u.stateStore.Set(state); err != nil {
			return err
		}
		u.configProvider.SetConfig(aws.Config{
			AccessKeyID:     config.awsAccessKeyID,
			SecretAccessKey: config.awsSecretAccessKey,
			Region:          config.awsRegion,
		})
	} else if u.awsCredentialsNotPresent(config) {
		err := u.awsCredentialValidator.Validate()
		if err != nil {
			return err
		}
	} else {
		return u.awsMissingCredentials(config)
	}

	err = u.checkForFastFails(state)
	if err != nil {
		return err
	}

	if state.EnvID == "" {
		state.EnvID, err = u.envIDGenerator.Generate()
		if err != nil {
			return err
		}
	}

	if state.KeyPair.Name == "" {
		state.KeyPair.Name = fmt.Sprintf("keypair-%s", state.EnvID)
	}

	if err := u.stateStore.Set(state); err != nil {
		return err
	}

	keyPair, err := u.keyPairSynchronizer.Sync(ec2.KeyPair{
		Name:       state.KeyPair.Name,
		PublicKey:  state.KeyPair.PublicKey,
		PrivateKey: state.KeyPair.PrivateKey,
	})
	if err != nil {
		return err
	}

	state.KeyPair.PublicKey = keyPair.PublicKey
	state.KeyPair.PrivateKey = keyPair.PrivateKey

	if err := u.stateStore.Set(state); err != nil {
		return err
	}

	availabilityZones, err := u.availabilityZoneRetriever.Retrieve(state.AWS.Region)
	if err != nil {
		return err
	}

	if state.Stack.Name == "" {
		stackEnvID := strings.Replace(state.EnvID, ":", "-", -1)
		state.Stack.Name = fmt.Sprintf("stack-%s", stackEnvID)

		if err := u.stateStore.Set(state); err != nil {
			return err
		}
	}

	var certificateARN string
	if lbExists(state.Stack.LBType) {
		certificate, err := u.certificateDescriber.Describe(state.Stack.CertificateName)
		if err != nil {
			return err
		}
		certificateARN = certificate.ARN
	}

	stack, err := u.infrastructureManager.Create(state.KeyPair.Name, len(availabilityZones), state.Stack.Name, state.Stack.LBType, certificateARN, state.EnvID)
	if err != nil {
		return err
	}

	infrastructureConfiguration := boshinit.InfrastructureConfiguration{
		AWSRegion:        state.AWS.Region,
		SubnetID:         stack.Outputs["BOSHSubnet"],
		AvailabilityZone: stack.Outputs["BOSHSubnetAZ"],
		ElasticIP:        stack.Outputs["BOSHEIP"],
		AccessKeyID:      stack.Outputs["BOSHUserAccessKey"],
		SecretAccessKey:  stack.Outputs["BOSHUserSecretAccessKey"],
		SecurityGroup:    stack.Outputs["BOSHSecurityGroup"],
	}

	deployInput, err := boshinit.NewDeployInput(state, infrastructureConfiguration, u.stringGenerator, state.EnvID)
	if err != nil {
		return err
	}

	deployOutput, err := u.boshDeployer.Deploy(deployInput)
	if err != nil {
		return err
	}

	if state.BOSH.IsEmpty() {
		state.BOSH = storage.BOSH{
			DirectorName:           deployInput.DirectorName,
			DirectorAddress:        stack.Outputs["BOSHURL"],
			DirectorUsername:       deployInput.DirectorUsername,
			DirectorPassword:       deployInput.DirectorPassword,
			DirectorSSLCA:          string(deployOutput.DirectorSSLKeyPair.CA),
			DirectorSSLCertificate: string(deployOutput.DirectorSSLKeyPair.Certificate),
			DirectorSSLPrivateKey:  string(deployOutput.DirectorSSLKeyPair.PrivateKey),
			Credentials:            deployOutput.Credentials,
		}
	}

	state.BOSH.State = deployOutput.BOSHInitState
	state.BOSH.Manifest = deployOutput.BOSHInitManifest

	err = u.stateStore.Set(state)
	if err != nil {
		return err
	}

	boshClient := u.boshClientProvider.Client(state.BOSH.DirectorAddress, state.BOSH.DirectorUsername,
		state.BOSH.DirectorPassword)

	cloudConfigInput := u.boshCloudConfigurator.Configure(stack, availabilityZones)

	err = u.cloudConfigManager.Update(cloudConfigInput, boshClient)
	if err != nil {
		return err
	}

	err = u.stateStore.Set(state)
	if err != nil {
		return err
	}

	return nil
}
								PrivateKey: "some-private-key",
								PublicKey:  "some-public-key",
							},
							BOSH: storage.BOSH{},
							Stack: storage.Stack{
								Name:            "some-stack-name",
								LBType:          "some-lb-type",
								CertificateName: "some-certificate-name",
							},
						}))
					})
				})

				Context("when there is no bosh to delete", func() {
					It("does not attempt to delete the bosh", func() {
						state.BOSH = storage.BOSH{}
						err := destroy.Execute([]string{}, state)
						Expect(err).NotTo(HaveOccurred())

						Expect(logger.PrintlnCall.Receives.Message).To(Equal("no BOSH director, skipping..."))
						Expect(boshDeleter.DeleteCall.CallCount).To(Equal(0))
					})
				})

				Context("when the certificate fails to delete", func() {
					It("removes the stack from the state and returns an error", func() {
						certificateDeleter.DeleteCall.Returns.Error = errors.New("failed to delete certificate")

						err := destroy.Execute([]string{}, state)
						Expect(err).To(MatchError("failed to delete certificate"))