Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var CreateStack = cli.Command{ Name: "create", Usage: "Generate an 'aws cloudformation create-stack' command", Flags: []cli.Flag{ &cli.StringFlag{Name: "provider-id", Required: true, Usage: "publisher/name@version"}, &cli.StringFlag{Name: "handler-id", Required: true, Usage: "The ID of the Handler (for example, 'cf-handler-aws')"}, &cli.StringFlag{Name: "bootstrap-bucket", Required: true}, &cli.StringFlag{Name: "common-fate-aws-account", Usage: "The AWS account where Common Fate is deployed"}, &cli.StringFlag{Name: "region", Usage: "The region to deploy the handler"}, }, Action: func(c *cli.Context) error { ctx := c.Context bootstrapBucket := c.String("bootstrap-bucket") handlerID := c.String("handler-id") commonFateAWSAccountID := c.String("common-fate-aws-account") registry, err := registryclient.New(ctx) if err != nil { return errors.Wrap(err, "configuring registry client") } providerString := c.String("provider-id") provider, err := providerregistrysdk.ParseProvider(providerString) if err != nil { return err } res, err := registry.GetProviderWithResponse(ctx, provider.Publisher, provider.Name, provider.Version) if err != nil { return err } var stackname = c.String("handler-id") if stackname == "" { err = survey.AskOne(&survey.Input{Message: "enter the cloudformation stackname:", Default: handlerID}, &stackname) if err != nil { return err } } var region = c.String("region") if region == "" { err = survey.AskOne(&survey.Input{Message: "enter the region of cloudformation stack deployment"}, ®ion) if err != nil { return err } } values := make(map[string]string) values["BootstrapBucketName"] = bootstrapBucket values["HandlerID"] = handlerID values["CommonFateAWSAccountID"] = commonFateAWSAccountID lambdaAssetPath := path.Join("registry.commonfate.io", "v1alpha1", "providers", provider.Publisher, provider.Name, provider.Version) values["AssetPath"] = path.Join(lambdaAssetPath, "handler.zip") awsCfg, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithRegion(region)) if err != nil { return err } config := res.JSON200.Schema.Config if config != nil { clio.Info("Enter the values for your configurations:") for k, v := range *config { if v.Secret != nil && *v.Secret { client := ssm.NewFromConfig(awsCfg) var secret string name := SSMKey(SSMKeyOpts{ HandlerID: handlerID, Key: k, Publisher: provider.Publisher, ProviderName: provider.Name, }) helpMsg := fmt.Sprintf("This will be stored in AWS SSM Parameter Store with name '%s'", name) err = survey.AskOne(&survey.Password{Message: k + ":", Help: helpMsg}, &secret) if err != nil { return err } _, err = client.PutParameter(ctx, &ssm.PutParameterInput{ Name: aws.String(name), Value: aws.String(secret), Type: types.ParameterTypeSecureString, Overwrite: aws.Bool(true), }) if err != nil { return err } clio.Successf("Added to AWS SSM Parameter Store with name '%s'", name) values[ConvertToPascalCase(k)+"Secret"] = name continue } var v string err = survey.AskOne(&survey.Input{Message: k + ":"}, &v) if err != nil { return err } values[ConvertToPascalCase(k)] = v } } if commonFateAWSAccountID == "" { var v string err = survey.AskOne(&survey.Input{Message: "The ID of the AWS account where Common Fate is deployed:"}, &v) if err != nil { return err } values["CommonFateAWSAccountID"] = v } parameterKeys := convertValuesToCloudformationParameter(values) s3client := s3.NewFromConfig(awsCfg) preSignedClient := s3.NewPresignClient(s3client) presigner := Presigner{ PresignClient: preSignedClient, } req, err := presigner.GetObject(bootstrapBucket, path.Join(lambdaAssetPath, "cloudformation.json"), int64(time.Hour)) if err != nil { return nil } templateUrl := fmt.Sprintf(" --template-url \"%s\" ", req.URL) stackNameFlag := fmt.Sprintf(" --stack-name %s ", stackname) regionFlag := fmt.Sprintf(" --region %s ", region) output := strings.Join([]string{"aws cloudformation create-stack", stackNameFlag, regionFlag, templateUrl, parameterKeys, "--capabilities CAPABILITY_NAMED_IAM"}, "") fmt.Printf("%v \n", output) return nil }, }
View Source
var GenerateCfOutput = cli.Command{ Name: "cloudformation", Usage: "Manage CloudFormation templates for Providers", Subcommands: []*cli.Command{ &cfnCommandCommand, }, }
View Source
var Login = cli.Command{
Name: "login",
Usage: "Log in to Common Fate",
Action: defaultLoginFlow.LoginAction,
}
View Source
var Logout = cli.Command{ Name: "logout", Usage: "Log out of Common Fate", Action: func(c *cli.Context) error { cfg, err := config.Load() if err != nil { return err } ts := tokenstore.New(cfg.CurrentContext) err = ts.Clear() if err != nil { return err } clio.Success("logged out") return nil }, }
View Source
var UpdateStack = cli.Command{ Name: "update", Usage: "Generate an 'aws cloudformation update-stack' command", Flags: []cli.Flag{ &cli.StringFlag{Name: "handler-id", Usage: "The Handler ID and name of the CloudFormation stack", Required: true}, &cli.StringFlag{Name: "region", Usage: "The region to deploy the handler", Required: true}, &cli.StringFlag{Name: "provider-id", Usage: "Update the provider-id for the current stack"}, &cli.BoolFlag{Name: "use-previous-value", Usage: "use the previous stack values for the parameters"}, }, Action: func(c *cli.Context) error { stackname := c.String("handler-id") region := c.String("region") ctx := c.Context awsCfg, err := awsconfig.LoadDefaultConfig(ctx, awsconfig.WithRegion(region)) if err != nil { return err } cfn := cloudformation.NewFromConfig(awsCfg) out, err := cfn.DescribeStacks(ctx, &cloudformation.DescribeStacksInput{ StackName: &stackname, }) if err != nil { return err } if len(out.Stacks) > 0 { stack := out.Stacks[0] values := make(map[string]string) if c.String("provider-id") != "" { registry, err := registryclient.New(ctx) if err != nil { return errors.Wrap(err, "configuring provider registry client") } provider, err := targetsvc.SplitProviderString(c.String("provider-id")) if err != nil { return err } _, err = registry.GetProviderWithResponse(ctx, provider.Publisher, provider.Name, provider.Version) if err != nil { return err } values["AssetPath"] = path.Join("registry.commonfate.io", "v1alpha1", "providers", provider.Publisher, provider.Name, provider.Version, "handler.zip") } for _, parameter := range stack.Parameters { if contains([]string{"HandlerID", "BootstrapBucketName"}, *parameter.ParameterKey) || c.Bool("use-previous-value") { values[*parameter.ParameterKey] = *parameter.ParameterValue continue } if strings.HasPrefix(*parameter.ParameterValue, "awsssm:///common-fate/provider/") { var shouldUpdate bool err = survey.AskOne(&survey.Confirm{Message: "Do you want to update value for " + *parameter.ParameterKey + " in AWS parameter store?"}, &shouldUpdate) if err != nil { return err } if shouldUpdate { client := ssm.NewFromConfig(awsCfg) var secret string name := *parameter.ParameterValue helpMsg := fmt.Sprintf("This will be stored in aws system manager parameter store with name '%s'", name) err = survey.AskOne(&survey.Password{Message: *parameter.ParameterKey + ":", Help: helpMsg}, &secret) if err != nil { return err } _, err = client.PutParameter(ctx, &ssm.PutParameterInput{ Name: aws.String(name), Value: aws.String(secret), Type: types.ParameterTypeSecureString, Overwrite: aws.Bool(true), }) if err != nil { return err } clio.Successf("Updated value in AWS System Manager Parameter Store for key with name '%s'", name) } continue } if c.String("provider-id") != "" && *parameter.ParameterKey == "AssetPath" { continue } var v string err = survey.AskOne(&survey.Input{Message: *parameter.ParameterKey + ":", Default: *parameter.ParameterValue}, &v) if err != nil { return err } if v != *parameter.ParameterValue { values[*parameter.ParameterKey] = v } else { values[*parameter.ParameterKey] = *parameter.ParameterValue } } parameterKeys := convertValuesToCloudformationParameter(values) s3client := s3.NewFromConfig(awsCfg) preSignedClient := s3.NewPresignClient(s3client) presigner := Presigner{ PresignClient: preSignedClient, } bootstrapBucket := values["BootstrapBucketName"] lambdaAssetPath := values["AssetPath"] req, err := presigner.GetObject(bootstrapBucket, strings.Replace(lambdaAssetPath, "handler.zip", "cloudformation.json", 1), int64(time.Hour)*1) if err != nil { return nil } templateUrl := fmt.Sprintf(" --template-url \"%s\" ", req.URL) stackNameFlag := fmt.Sprintf(" --stack-name %s ", stackname) regionFlag := fmt.Sprintf(" --region %s ", region) output := strings.Join([]string{"aws cloudformation update-stack", stackNameFlag, regionFlag, templateUrl, parameterKeys, "--capabilities CAPABILITY_NAMED_IAM"}, "") fmt.Printf("%v \n", output) } return nil }, }
Functions ¶
func ConvertToPascalCase ¶ added in v0.2.0
func SSMKey ¶ added in v0.2.0
func SSMKey(opts SSMKeyOpts) string
this will create a unique identifier for AWS System Manager Parameter Store for configuration field "api_url" this will result: 'publisher/provider-name/version/configuration/api_url'
Types ¶
type LoginFlow ¶
type Presigner ¶ added in v0.2.0
type Presigner struct {
PresignClient *s3.PresignClient
}
func (Presigner) GetObject ¶ added in v0.2.0
func (presigner Presigner) GetObject( bucketName string, objectKey string, lifetimeSecs int64) (*v4.PresignedHTTPRequest, error)
GetObject makes a presigned request that can be used to get an object from a bucket. The presigned request is valid for the specified number of seconds.
Click to show internal directories.
Click to hide internal directories.