func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) { if c.GlobalIsSet("http-timeout") { acme.HTTPClient = http.Client{Timeout: time.Duration(c.GlobalInt("http-timeout")) * time.Second} } if c.GlobalIsSet("dns-timeout") { acme.DNSTimeout = time.Duration(c.GlobalInt("dns-timeout")) * time.Second } if len(c.GlobalStringSlice("dns-resolvers")) > 0 { resolvers := []string{} for _, resolver := range c.GlobalStringSlice("dns-resolvers") { if !strings.Contains(resolver, ":") { resolver += ":53" } resolvers = append(resolvers, resolver) } acme.RecursiveNameservers = resolvers } err := checkFolder(c.GlobalString("path")) if err != nil { logger().Fatalf("Could not check/create path: %s", err.Error()) } conf := NewConfiguration(c) if len(c.GlobalString("email")) == 0 { logger().Fatal("You have to pass an account (email address) to the program using --email or -m") } //TODO: move to account struct? Currently MUST pass email. acc := NewAccount(c.GlobalString("email"), conf) keyType, err := conf.KeyType() if err != nil { logger().Fatal(err.Error()) } client, err := acme.NewClient(c.GlobalString("server"), acc, keyType) if err != nil { logger().Fatalf("Could not create client: %s", err.Error()) } if len(c.GlobalStringSlice("exclude")) > 0 { client.ExcludeChallenges(conf.ExcludedSolvers()) } if c.GlobalIsSet("webroot") { provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot")) if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.HTTP01, provider) // --webroot=foo indicates that the user specifically want to do a HTTP challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01}) } if c.GlobalIsSet("memcached-host") { provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host")) if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.HTTP01, provider) // --memcached-host=foo:11211 indicates that the user specifically want to do a HTTP challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01}) } if c.GlobalIsSet("http") { if strings.Index(c.GlobalString("http"), ":") == -1 { logger().Fatalf("The --http switch only accepts interface:port or :port for its argument.") } client.SetHTTPAddress(c.GlobalString("http")) } if c.GlobalIsSet("tls") { if strings.Index(c.GlobalString("tls"), ":") == -1 { logger().Fatalf("The --tls switch only accepts interface:port or :port for its argument.") } client.SetTLSAddress(c.GlobalString("tls")) } if c.GlobalIsSet("dns") { var err error var provider acme.ChallengeProvider switch c.GlobalString("dns") { case "azure": provider, err = azure.NewDNSProvider() case "auroradns": provider, err = auroradns.NewDNSProvider() case "cloudflare": provider, err = cloudflare.NewDNSProvider() case "digitalocean": provider, err = digitalocean.NewDNSProvider() case "dnsimple": provider, err = dnsimple.NewDNSProvider() case "dnsmadeeasy": provider, err = dnsmadeeasy.NewDNSProvider() case "exoscale": provider, err = exoscale.NewDNSProvider() case "dyn": provider, err = dyn.NewDNSProvider() case "gandi": provider, err = gandi.NewDNSProvider() case "gcloud": provider, err = googlecloud.NewDNSProvider() case "linode": provider, err = linode.NewDNSProvider() case "manual": provider, err = acme.NewDNSProviderManual() case "namecheap": provider, err = namecheap.NewDNSProvider() case "rackspace": provider, err = rackspace.NewDNSProvider() case "route53": provider, err = route53.NewDNSProvider() case "rfc2136": provider, err = rfc2136.NewDNSProvider() case "vultr": provider, err = vultr.NewDNSProvider() case "ovh": provider, err = ovh.NewDNSProvider() case "pdns": provider, err = pdns.NewDNSProvider() case "ns1": provider, err = ns1.NewDNSProvider() case "dnspod": provider, err = dnspod.NewDNSProvider() } if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.DNS01, provider) // --dns=foo indicates that the user specifically want to do a DNS challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01}) } return conf, acc, client }
func run(c *cli.Context) error { PrintBitriseHeaderASCIIArt(version.VERSION) // // Expand cli.Context var prGlobalFlagPtr *bool if c.GlobalIsSet(PRKey) { prGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(PRKey)) } var ciGlobalFlagPtr *bool if c.GlobalIsSet(CIKey) { ciGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(CIKey)) } workflowToRunID := c.String(WorkflowKey) if workflowToRunID == "" && len(c.Args()) > 0 { workflowToRunID = c.Args()[0] } bitriseConfigBase64Data := c.String(ConfigBase64Key) bitriseConfigPath := c.String(ConfigKey) deprecatedBitriseConfigPath := c.String(PathKey) if bitriseConfigPath == "" && deprecatedBitriseConfigPath != "" { log.Warn("'path' key is deprecated, use 'config' instead!") bitriseConfigPath = deprecatedBitriseConfigPath } inventoryBase64Data := c.String(InventoryBase64Key) inventoryPath := c.String(InventoryKey) jsonParams := c.String(JSONParamsKey) jsonParamsBase64 := c.String(JSONParamsBase64Key) runParams, err := parseRunParams( workflowToRunID, bitriseConfigPath, bitriseConfigBase64Data, inventoryPath, inventoryBase64Data, jsonParams, jsonParamsBase64) if err != nil { return fmt.Errorf("Failed to parse command params, error: %s", err) } // // Inventory validation inventoryEnvironments, err := CreateInventoryFromCLIParams(runParams.InventoryBase64Data, runParams.InventoryPath) if err != nil { log.Fatalf("Failed to create inventory, error: %s", err) } // Config validation bitriseConfig, warnings, err := CreateBitriseConfigFromCLIParams(runParams.BitriseConfigBase64Data, runParams.BitriseConfigPath) for _, warning := range warnings { log.Warnf("warning: %s", warning) } if err != nil { log.Fatalf("Failed to create bitrise config, error: %s", err) } // Workflow id validation if runParams.WorkflowToRunID == "" { // no workflow specified // list all the available ones and then exit log.Error("No workfow specified!") fmt.Println() printAvailableWorkflows(bitriseConfig) os.Exit(1) } if strings.HasPrefix(runParams.WorkflowToRunID, "_") { // util workflow specified // print about util workflows and then exit log.Error("Utility workflows can't be triggered directly") fmt.Println() printAboutUtilityWorkflowsText() os.Exit(1) } // // // Main isPRMode, err := isPRMode(prGlobalFlagPtr, inventoryEnvironments) if err != nil { log.Fatalf("Failed to check PR mode, error: %s", err) } if err := registerPrMode(isPRMode); err != nil { log.Fatalf("Failed to register PR mode, error: %s", err) } isCIMode, err := isCIMode(ciGlobalFlagPtr, inventoryEnvironments) if err != nil { log.Fatalf("Failed to check CI mode, error: %s", err) } if err := registerCIMode(isCIMode); err != nil { log.Fatalf("Failed to register CI mode, error: %s", err) } log.Infoln(colorstring.Green("Running workflow:"), runParams.WorkflowToRunID) runAndExit(bitriseConfig, inventoryEnvironments, runParams.WorkflowToRunID) // return nil }
func setup(c *cli.Context) (*Configuration, *Account, *acme.Client) { if c.GlobalIsSet("http-timeout") { acme.HTTPClient = http.Client{Timeout: time.Duration(c.GlobalInt("http-timeout")) * time.Second} } if c.GlobalIsSet("dns-timeout") { acme.DNSTimeout = time.Duration(c.GlobalInt("dns-timeout")) * time.Second } if len(c.GlobalStringSlice("dns-resolvers")) > 0 { resolvers := []string{} for _, resolver := range c.GlobalStringSlice("dns-resolvers") { if !strings.Contains(resolver, ":") { resolver += ":53" } resolvers = append(resolvers, resolver) } acme.RecursiveNameservers = resolvers } err := checkFolder(c.GlobalString("path")) if err != nil { logger().Fatalf("Could not check/create path: %s", err.Error()) } conf := NewConfiguration(c) if len(c.GlobalString("email")) == 0 { logger().Fatal("You have to pass an account (email address) to the program using --email or -m") } //TODO: move to account struct? Currently MUST pass email. acc := NewAccount(c.GlobalString("email"), conf) keyType, err := conf.KeyType() if err != nil { logger().Fatal(err.Error()) } client, err := acme.NewClient(c.GlobalString("server"), acc, keyType) if err != nil { logger().Fatalf("Could not create client: %s", err.Error()) } if len(c.GlobalStringSlice("exclude")) > 0 { client.ExcludeChallenges(conf.ExcludedSolvers()) } if c.GlobalIsSet("webroot") { provider, err := webroot.NewHTTPProvider(c.GlobalString("webroot")) if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.HTTP01, provider) // --webroot=foo indicates that the user specifically want to do a HTTP challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01}) } if c.GlobalIsSet("memcached-host") { provider, err := memcached.NewMemcachedProvider(c.GlobalStringSlice("memcached-host")) if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.HTTP01, provider) // --memcached-host=foo:11211 indicates that the user specifically want to do a HTTP challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.DNS01, acme.TLSSNI01}) } if c.GlobalIsSet("http") { if strings.Index(c.GlobalString("http"), ":") == -1 { logger().Fatalf("The --http switch only accepts interface:port or :port for its argument.") } client.SetHTTPAddress(c.GlobalString("http")) } if c.GlobalIsSet("tls") { if strings.Index(c.GlobalString("tls"), ":") == -1 { logger().Fatalf("The --tls switch only accepts interface:port or :port for its argument.") } client.SetTLSAddress(c.GlobalString("tls")) } if c.GlobalIsSet("dns") { provider, err := dns.NewDNSChallengeProviderByName(c.GlobalString("dns")) if err != nil { logger().Fatal(err) } client.SetChallengeProvider(acme.DNS01, provider) // --dns=foo indicates that the user specifically want to do a DNS challenge // infer that the user also wants to exclude all other challenges client.ExcludeChallenges([]acme.Challenge{acme.HTTP01, acme.TLSSNI01}) } return conf, acc, client }
func triggerCheck(c *cli.Context) error { warnings := []string{} // // Expand cli.Context var prGlobalFlagPtr *bool if c.GlobalIsSet(PRKey) { prGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(PRKey)) } triggerPattern := c.String(PatternKey) if triggerPattern == "" && len(c.Args()) > 0 { triggerPattern = c.Args()[0] } pushBranch := c.String(PushBranchKey) prSourceBranch := c.String(PRSourceBranchKey) prTargetBranch := c.String(PRTargetBranchKey) tag := c.String(TagKey) bitriseConfigBase64Data := c.String(ConfigBase64Key) bitriseConfigPath := c.String(ConfigKey) deprecatedBitriseConfigPath := c.String(PathKey) if bitriseConfigPath == "" && deprecatedBitriseConfigPath != "" { warnings = append(warnings, "'path' key is deprecated, use 'config' instead!") bitriseConfigPath = deprecatedBitriseConfigPath } inventoryBase64Data := c.String(InventoryBase64Key) inventoryPath := c.String(InventoryKey) jsonParams := c.String(JSONParamsKey) jsonParamsBase64 := c.String(JSONParamsBase64Key) format := c.String(OuputFormatKey) triggerParams, err := parseTriggerCheckParams( triggerPattern, pushBranch, prSourceBranch, prTargetBranch, tag, format, bitriseConfigPath, bitriseConfigBase64Data, inventoryPath, inventoryBase64Data, jsonParams, jsonParamsBase64) if err != nil { registerFatal(fmt.Sprintf("Failed to parse trigger check params, err: %s", err), warnings, triggerParams.Format) } // // Inventory validation inventoryEnvironments, err := CreateInventoryFromCLIParams(triggerParams.InventoryBase64Data, triggerParams.InventoryPath) if err != nil { registerFatal(fmt.Sprintf("Failed to create inventory, err: %s", err), warnings, triggerParams.Format) } // Config validation bitriseConfig, warns, err := CreateBitriseConfigFromCLIParams(triggerParams.BitriseConfigBase64Data, triggerParams.BitriseConfigPath) warnings = append(warnings, warns...) if err != nil { registerFatal(fmt.Sprintf("Failed to create config, err: %s", err), warnings, triggerParams.Format) } // Format validation if triggerParams.Format == "" { triggerParams.Format = output.FormatRaw } else if !(triggerParams.Format == output.FormatRaw || triggerParams.Format == output.FormatJSON) { registerFatal(fmt.Sprintf("Invalid format: %s", triggerParams.Format), warnings, output.FormatJSON) } // Trigger filter validation if triggerParams.TriggerPattern == "" && triggerParams.PushBranch == "" && triggerParams.PRSourceBranch == "" && triggerParams.PRTargetBranch == "" && triggerParams.Tag == "" { registerFatal("No trigger pattern nor trigger params specified", warnings, triggerParams.Format) } // // // Main isPRMode, err := isPRMode(prGlobalFlagPtr, inventoryEnvironments) if err != nil { registerFatal(fmt.Sprintf("Failed to check PR mode, err: %s", err), warnings, triggerParams.Format) } workflowToRunID, err := getWorkflowIDByParamsInCompatibleMode(bitriseConfig.TriggerMap, triggerParams, isPRMode) if err != nil { registerFatal(err.Error(), warnings, triggerParams.Format) } triggerModel := map[string]string{"workflow": workflowToRunID} if triggerParams.TriggerPattern != "" { triggerModel["pattern"] = triggerParams.TriggerPattern } else { if triggerParams.PushBranch != "" { triggerModel["push-branch"] = triggerParams.PushBranch } else if triggerParams.PRSourceBranch != "" || triggerParams.PRTargetBranch != "" { if triggerParams.PRSourceBranch != "" { triggerModel["pr-source-branch"] = triggerParams.PRSourceBranch } if triggerParams.PRTargetBranch != "" { triggerModel["pr-target-branch"] = triggerParams.PRTargetBranch } } else if triggerParams.Tag != "" { triggerModel["tag"] = triggerParams.Tag } } switch triggerParams.Format { case output.FormatRaw: msg := "" for key, value := range triggerModel { if key == "workflow" { msg = msg + fmt.Sprintf("-> %s", colorstring.Blue(value)) } else { msg = fmt.Sprintf("%s: %s ", key, value) + msg } } fmt.Println(msg) break case output.FormatJSON: bytes, err := json.Marshal(triggerModel) if err != nil { registerFatal(fmt.Sprintf("Failed to parse trigger model, err: %s", err), warnings, triggerParams.Format) } fmt.Println(string(bytes)) break default: registerFatal(fmt.Sprintf("Invalid format: %s", triggerParams.Format), warnings, output.FormatJSON) } // return nil }
func trigger(c *cli.Context) error { PrintBitriseHeaderASCIIArt(version.VERSION) // Expand cli.Context var prGlobalFlagPtr *bool if c.GlobalIsSet(PRKey) { prGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(PRKey)) } var ciGlobalFlagPtr *bool if c.GlobalIsSet(CIKey) { ciGlobalFlagPtr = pointers.NewBoolPtr(c.GlobalBool(CIKey)) } triggerPattern := c.String(PatternKey) if triggerPattern == "" && len(c.Args()) > 0 { triggerPattern = c.Args()[0] } pushBranch := c.String(PushBranchKey) prSourceBranch := c.String(PRSourceBranchKey) prTargetBranch := c.String(PRTargetBranchKey) tag := c.String(TagKey) bitriseConfigBase64Data := c.String(ConfigBase64Key) bitriseConfigPath := c.String(ConfigKey) deprecatedBitriseConfigPath := c.String(PathKey) if bitriseConfigPath == "" && deprecatedBitriseConfigPath != "" { log.Warn("'path' key is deprecated, use 'config' instead!") bitriseConfigPath = deprecatedBitriseConfigPath } inventoryBase64Data := c.String(InventoryBase64Key) inventoryPath := c.String(InventoryKey) jsonParams := c.String(JSONParamsKey) jsonParamsBase64 := c.String(JSONParamsBase64Key) triggerParams, err := parseTriggerParams( triggerPattern, pushBranch, prSourceBranch, prTargetBranch, tag, bitriseConfigPath, bitriseConfigBase64Data, inventoryPath, inventoryBase64Data, jsonParams, jsonParamsBase64) if err != nil { return fmt.Errorf("Failed to parse trigger command params, error: %s", err) } // Inventory validation inventoryEnvironments, err := CreateInventoryFromCLIParams(triggerParams.InventoryBase64Data, triggerParams.InventoryPath) if err != nil { log.Fatalf("Failed to create inventory, error: %s", err) } // Config validation bitriseConfig, warnings, err := CreateBitriseConfigFromCLIParams(triggerParams.BitriseConfigBase64Data, triggerParams.BitriseConfigPath) for _, warning := range warnings { log.Warnf("warning: %s", warning) } if err != nil { log.Fatalf("Failed to create bitrise config, error: %s", err) } // Trigger filter validation if triggerParams.TriggerPattern == "" && triggerParams.PushBranch == "" && triggerParams.PRSourceBranch == "" && triggerParams.PRTargetBranch == "" && triggerParams.Tag == "" { log.Error("No trigger pattern nor trigger params specified") printAvailableTriggerFilters(bitriseConfig.TriggerMap) os.Exit(1) } // // Main isPRMode, err := isPRMode(prGlobalFlagPtr, inventoryEnvironments) if err != nil { log.Fatalf("Failed to check PR mode, error: %s", err) } if err := registerPrMode(isPRMode); err != nil { log.Fatalf("Failed to register PR mode, error: %s", err) } isCIMode, err := isCIMode(ciGlobalFlagPtr, inventoryEnvironments) if err != nil { log.Fatalf("Failed to check CI mode, error: %s", err) } if err := registerCIMode(isCIMode); err != nil { log.Fatalf("Failed to register CI mode, error: %s", err) } workflowToRunID, err := getWorkflowIDByParamsInCompatibleMode(bitriseConfig.TriggerMap, triggerParams, isPRMode) if err != nil { log.Errorf("Failed to get workflow id by pattern, error: %s", err) if strings.Contains(err.Error(), "no matching workflow found with trigger params:") { printAvailableTriggerFilters(bitriseConfig.TriggerMap) } os.Exit(1) } if triggerParams.TriggerPattern != "" { log.Infof("pattern (%s) triggered workflow (%s)", triggerParams.TriggerPattern, workflowToRunID) } else { if triggerParams.PushBranch != "" { log.Infof("push-branch (%s) triggered workflow (%s)", triggerParams.PushBranch, workflowToRunID) } else if triggerParams.PRSourceBranch != "" || triggerParams.PRTargetBranch != "" { log.Infof("pr-source-branch (%s) and pr-target-branch (%s) triggered workflow (%s)", triggerParams.PRSourceBranch, triggerParams.PRTargetBranch, workflowToRunID) } else if triggerParams.Tag != "" { log.Infof("tag (%s) triggered workflow (%s)", triggerParams.Tag, workflowToRunID) } } runAndExit(bitriseConfig, inventoryEnvironments, workflowToRunID) // return nil }
// // handleCommand is a generic wrapper for handling commands, or more precisely their errors // func handleCommand(cx *cli.Context, options []string, cmd *cliCommand, method func(*formatter, *cli.Context, *cliCommand) error) error { // step: handle any panics in the command defer func() { if r := recover(); r != nil { fmt.Fprintf(os.Stderr, "[error] internal error occurred, message: %s", r) os.Exit(1) } }() // step: check the required options were specified for _, k := range options { items := strings.Split(k, ":") if len(items) != 3 { panic("invalid required option definition, SCOPE:NAME:TYPE") } name := items[1] // // @Fix the cli lib IsSet does not check if the option was set by a environment variable, the // issue https://github.com/urfave/cli/issues/294 highlights problem. As a consequence, we can't determine // if the variable is actually set. The hack below attempts to remedy it. // var invalid bool switch scope := items[0]; scope { case "g": switch t := items[2]; t { case "s": invalid = !cx.GlobalIsSet(name) && cx.String(name) == "" case "a": invalid = !cx.GlobalIsSet(name) && len(cx.GlobalStringSlice(name)) == 0 } if invalid { printError("the global option: '%s' is required", name) } default: switch t := items[2]; t { case "s": invalid = !cx.IsSet(name) && cx.String(name) == "" case "a": invalid = !cx.IsSet(name) && len(cx.StringSlice(name)) == 0 } if invalid { printError("the command option: '%s' is required", name) } } } // step: create a cli output writer, err := newFormatter(cx.GlobalString("format"), os.Stdout) if err != nil { printError("error: %s", err) } // step: call the command and handle any errors if err := method(writer, cx, cmd); err != nil { printError("operation failed, error: %s", err) } return nil }