func main() {
	// Utilities
	uuidGenerator := helpers.NewUUIDGenerator(rand.Reader)
	stringGenerator := helpers.NewStringGenerator(rand.Reader)
	logger := application.NewLogger(os.Stdout)
	stateStore := storage.NewStore()
	sslKeyPairGenerator := ssl.NewKeyPairGenerator(time.Now, rsa.GenerateKey, x509.CreateCertificate)

	// Usage Command
	usage := commands.NewUsage(os.Stdout)

	commandLineParser := application.NewCommandLineParser(usage.Print)
	configurationParser := application.NewConfigurationParser(commandLineParser, stateStore)
	configuration, err := configurationParser.Parse(os.Args[1:])
	if err != nil {
		fail(err)
	}

	// Amazon
	awsConfiguration := aws.Config{
		AccessKeyID:      configuration.State.AWS.AccessKeyID,
		SecretAccessKey:  configuration.State.AWS.SecretAccessKey,
		Region:           configuration.State.AWS.Region,
		EndpointOverride: configuration.Global.EndpointOverride,
	}

	cloudFormationClient := cloudformation.NewClient(awsConfiguration)
	ec2Client := ec2.NewClient(awsConfiguration)
	iamClient := iam.NewClient(awsConfiguration)

	awsCredentialValidator := application.NewAWSCredentialValidator(configuration)
	vpcStatusChecker := ec2.NewVPCStatusChecker(ec2Client)
	keyPairCreator := ec2.NewKeyPairCreator(ec2Client, uuidGenerator)
	keyPairDeleter := ec2.NewKeyPairDeleter(ec2Client, logger)
	keyPairChecker := ec2.NewKeyPairChecker(ec2Client)
	keyPairManager := ec2.NewKeyPairManager(keyPairCreator, keyPairChecker, logger)
	keyPairSynchronizer := ec2.NewKeyPairSynchronizer(keyPairManager)
	availabilityZoneRetriever := ec2.NewAvailabilityZoneRetriever(ec2Client)
	templateBuilder := templates.NewTemplateBuilder(logger)
	stackManager := cloudformation.NewStackManager(cloudFormationClient, logger)
	infrastructureManager := cloudformation.NewInfrastructureManager(templateBuilder, stackManager)
	certificateUploader := iam.NewCertificateUploader(iamClient, uuidGenerator)
	certificateDescriber := iam.NewCertificateDescriber(iamClient)
	certificateDeleter := iam.NewCertificateDeleter(iamClient)
	certificateManager := iam.NewCertificateManager(certificateUploader, certificateDescriber, certificateDeleter)
	certificateValidator := iam.NewCertificateValidator()

	// bosh-init
	tempDir, err := ioutil.TempDir("", "bosh-init")
	if err != nil {
		fail(err)
	}

	boshInitPath, err := exec.LookPath("bosh-init")
	if err != nil {
		fail(err)
	}

	cloudProviderManifestBuilder := manifests.NewCloudProviderManifestBuilder(stringGenerator)
	jobsManifestBuilder := manifests.NewJobsManifestBuilder(stringGenerator)
	boshinitManifestBuilder := manifests.NewManifestBuilder(
		logger, sslKeyPairGenerator, stringGenerator, cloudProviderManifestBuilder, jobsManifestBuilder,
	)
	boshinitCommandBuilder := boshinit.NewCommandBuilder(boshInitPath, tempDir, os.Stdout, os.Stderr)
	boshinitDeployCommand := boshinitCommandBuilder.DeployCommand()
	boshinitDeleteCommand := boshinitCommandBuilder.DeleteCommand()
	boshinitDeployRunner := boshinit.NewCommandRunner(tempDir, boshinitDeployCommand)
	boshinitDeleteRunner := boshinit.NewCommandRunner(tempDir, boshinitDeleteCommand)
	boshinitExecutor := boshinit.NewExecutor(
		boshinitManifestBuilder, boshinitDeployRunner, boshinitDeleteRunner, logger,
	)

	// BOSH
	boshClientProvider := bosh.NewClientProvider()
	cloudConfigGenerator := bosh.NewCloudConfigGenerator()
	cloudConfigurator := bosh.NewCloudConfigurator(logger, cloudConfigGenerator)
	cloudConfigManager := bosh.NewCloudConfigManager(logger, cloudConfigGenerator)

	// Commands
	help := commands.NewUsage(os.Stdout)
	version := commands.NewVersion(os.Stdout)
	up := commands.NewUp(
		awsCredentialValidator, infrastructureManager, keyPairSynchronizer, boshinitExecutor,
		stringGenerator, cloudConfigurator, availabilityZoneRetriever, certificateDescriber,
		cloudConfigManager, boshClientProvider,
	)
	destroy := commands.NewDestroy(
		awsCredentialValidator, logger, os.Stdin, boshinitExecutor, vpcStatusChecker, stackManager,
		stringGenerator, infrastructureManager, keyPairDeleter, certificateDeleter,
	)
	createLBs := commands.NewCreateLBs(
		logger, awsCredentialValidator, certificateManager, infrastructureManager,
		availabilityZoneRetriever, boshClientProvider, cloudConfigurator, cloudConfigManager, certificateValidator,
	)
	updateLBs := commands.NewUpdateLBs(awsCredentialValidator, certificateManager,
		availabilityZoneRetriever, infrastructureManager, boshClientProvider, logger, certificateValidator,
	)
	deleteLBs := commands.NewDeleteLBs(
		awsCredentialValidator, availabilityZoneRetriever, certificateManager,
		infrastructureManager, logger, cloudConfigurator, cloudConfigManager, boshClientProvider,
	)
	lbs := commands.NewLBs(awsCredentialValidator, infrastructureManager, os.Stdout)
	directorAddress := commands.NewStateQuery(logger, "director address", func(state storage.State) string {
		return state.BOSH.DirectorAddress
	})
	directorUsername := commands.NewStateQuery(logger, "director username", func(state storage.State) string {
		return state.BOSH.DirectorUsername
	})
	directorPassword := commands.NewStateQuery(logger, "director password", func(state storage.State) string {
		return state.BOSH.DirectorPassword
	})
	sshKey := commands.NewStateQuery(logger, "ssh key", func(state storage.State) string {
		return state.KeyPair.PrivateKey
	})

	app := application.New(application.CommandSet{
		"help":    help,
		"version": version,
		"unsupported-deploy-bosh-on-aws-for-concourse": up,
		"destroy":                   destroy,
		"director-address":          directorAddress,
		"director-username":         directorUsername,
		"director-password":         directorPassword,
		"ssh-key":                   sshKey,
		commands.CREATE_LBS_COMMAND: createLBs,
		"unsupported-update-lbs":    updateLBs,
		"unsupported-delete-lbs":    deleteLBs,
		"lbs": lbs,
	}, configuration, stateStore, usage.Print)

	err = app.Run()
	if err != nil {
		fail(err)
	}
}
				AWS: storage.AWS{
					AccessKeyID:     "some-access-key-id",
					SecretAccessKey: "some-secret-access-key",
					Region:          "some-region",
				},
				KeyPair: storage.KeyPair{
					Name: "some-key-pair",
				},
				BOSH: storage.BOSH{
					DirectorAddress:  "some-director-address",
					DirectorUsername: "******",
					DirectorPassword: "******",
				},
			}

			command = commands.NewCreateLBs(logger, awsCredentialValidator, certificateManager, infrastructureManager,
				availabilityZoneRetriever, boshClientProvider, boshCloudConfigurator, cloudConfigManager, certificateValidator)
		})

		It("returns an error if aws credential validator fails", func() {
			awsCredentialValidator.ValidateCall.Returns.Error = errors.New("failed to validate aws credentials")
			_, err := command.Execute([]string{}, storage.State{})
			Expect(err).To(MatchError("failed to validate aws credentials"))
		})

		It("uploads a cert and key", func() {
			_, err := command.Execute([]string{
				"--type", "concourse",
				"--cert", "temp/some-cert.crt",
				"--key", "temp/some-key.key",
			}, storage.State{})
			Expect(err).NotTo(HaveOccurred())