chore: migrate to github.com/urfave/cli/v2 (#1590)

This commit is contained in:
Ludovic Fernandez 2022-02-13 12:28:51 +01:00 committed by GitHub
parent 6d474ebb65
commit 7d9176bd0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 181 additions and 171 deletions

View file

@ -16,7 +16,7 @@ import (
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const ( const (
@ -73,12 +73,12 @@ func NewAccountsStorage(ctx *cli.Context) *AccountsStorage {
// TODO: move to account struct? Currently MUST pass email. // TODO: move to account struct? Currently MUST pass email.
email := getEmail(ctx) email := getEmail(ctx)
serverURL, err := url.Parse(ctx.GlobalString("server")) serverURL, err := url.Parse(ctx.String("server"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
rootPath := filepath.Join(ctx.GlobalString("path"), baseAccountsRootFolderName) rootPath := filepath.Join(ctx.String("path"), baseAccountsRootFolderName)
serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host) serverPath := strings.NewReplacer(":", "_", "/", string(os.PathSeparator)).Replace(serverURL.Host)
accountsPath := filepath.Join(rootPath, serverPath) accountsPath := filepath.Join(rootPath, serverPath)
rootUserPath := filepath.Join(accountsPath, email) rootUserPath := filepath.Join(accountsPath, email)
@ -226,7 +226,7 @@ func loadPrivateKey(file string) (crypto.PrivateKey, error) {
func tryRecoverRegistration(ctx *cli.Context, privateKey crypto.PrivateKey) (*registration.Resource, error) { func tryRecoverRegistration(ctx *cli.Context, privateKey crypto.PrivateKey) (*registration.Resource, error) {
// couldn't load account but got a key. Try to look the account up. // couldn't load account but got a key. Try to look the account up.
config := lego.NewConfig(&Account{key: privateKey}) config := lego.NewConfig(&Account{key: privateKey})
config.CADirURL = ctx.GlobalString("server") config.CADirURL = ctx.String("server")
config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version) config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version)
client, err := lego.NewClient(config) client, err := lego.NewClient(config)

View file

@ -17,7 +17,7 @@ import (
"github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
"golang.org/x/net/idna" "golang.org/x/net/idna"
"software.sslmate.com/src/go-pkcs12" "software.sslmate.com/src/go-pkcs12"
) )
@ -53,12 +53,12 @@ type CertificatesStorage struct {
// NewCertificatesStorage create a new certificates storage. // NewCertificatesStorage create a new certificates storage.
func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage { func NewCertificatesStorage(ctx *cli.Context) *CertificatesStorage {
return &CertificatesStorage{ return &CertificatesStorage{
rootPath: filepath.Join(ctx.GlobalString("path"), baseCertificatesFolderName), rootPath: filepath.Join(ctx.String("path"), baseCertificatesFolderName),
archivePath: filepath.Join(ctx.GlobalString("path"), baseArchivesFolderName), archivePath: filepath.Join(ctx.String("path"), baseArchivesFolderName),
pem: ctx.GlobalBool("pem"), pem: ctx.Bool("pem"),
pfx: ctx.GlobalBool("pfx"), pfx: ctx.Bool("pfx"),
pfxPassword: ctx.GlobalString("pfx.pass"), pfxPassword: ctx.String("pfx.pass"),
filename: ctx.GlobalString("filename"), filename: ctx.String("filename"),
} }
} }

View file

@ -1,10 +1,10 @@
package cmd package cmd
import "github.com/urfave/cli" import "github.com/urfave/cli/v2"
// CreateCommands Creates all CLI commands. // CreateCommands Creates all CLI commands.
func CreateCommands() []cli.Command { func CreateCommands() []*cli.Command {
return []cli.Command{ return []*cli.Command{
createRun(), createRun(),
createRevoke(), createRevoke(),
createRenew(), createRenew(),

View file

@ -2,20 +2,20 @@ package cmd
import ( import (
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func Before(ctx *cli.Context) error { func Before(ctx *cli.Context) error {
if ctx.GlobalString("path") == "" { if ctx.String("path") == "" {
log.Fatal("Could not determine current working directory. Please pass --path.") log.Fatal("Could not determine current working directory. Please pass --path.")
} }
err := createNonExistingFolder(ctx.GlobalString("path")) err := createNonExistingFolder(ctx.String("path"))
if err != nil { if err != nil {
log.Fatalf("Could not check/create path: %v", err) log.Fatalf("Could not check/create path: %v", err)
} }
if ctx.GlobalString("server") == "" { if ctx.String("server") == "" {
log.Fatal("Could not determine current working server. Please pass --server.") log.Fatal("Could not determine current working server. Please pass --server.")
} }

View file

@ -7,17 +7,18 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func createDNSHelp() cli.Command { func createDNSHelp() *cli.Command {
return cli.Command{ return &cli.Command{
Name: "dnshelp", Name: "dnshelp",
Usage: "Shows additional help for the '--dns' global option", Usage: "Shows additional help for the '--dns' global option",
Action: dnsHelp, Action: dnsHelp,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "code, c", Name: "code",
Aliases: []string{"c"},
Usage: fmt.Sprintf("DNS code: %s", allDNSCodes()), Usage: fmt.Sprintf("DNS code: %s", allDNSCodes()),
}, },
}, },

View file

@ -9,21 +9,23 @@ import (
"strings" "strings"
"github.com/go-acme/lego/v4/certcrypto" "github.com/go-acme/lego/v4/certcrypto"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func createList() cli.Command { func createList() *cli.Command {
return cli.Command{ return &cli.Command{
Name: "list", Name: "list",
Usage: "Display certificates and accounts information.", Usage: "Display certificates and accounts information.",
Action: list, Action: list,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "accounts, a", Name: "accounts",
Aliases: []string{"a"},
Usage: "Display accounts.", Usage: "Display accounts.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "names, n", Name: "names",
Aliases: []string{"n"},
Usage: "Display certificate common names only.", Usage: "Display certificate common names only.",
}, },
}, },
@ -92,7 +94,7 @@ func listCertificates(ctx *cli.Context) error {
func listAccount(ctx *cli.Context) error { func listAccount(ctx *cli.Context) error {
// fake email, needed by NewAccountsStorage // fake email, needed by NewAccountsStorage
if err := ctx.GlobalSet("email", "unknown"); err != nil { if err := ctx.Set("email", "unknown"); err != nil {
return err return err
} }

View file

@ -9,7 +9,7 @@ import (
"github.com/go-acme/lego/v4/certificate" "github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const ( const (
@ -19,15 +19,15 @@ const (
renewEnvCertKeyPath = "LEGO_CERT_KEY_PATH" renewEnvCertKeyPath = "LEGO_CERT_KEY_PATH"
) )
func createRenew() cli.Command { func createRenew() *cli.Command {
return cli.Command{ return &cli.Command{
Name: "renew", Name: "renew",
Usage: "Renew a certificate", Usage: "Renew a certificate",
Action: renew, Action: renew,
Before: func(ctx *cli.Context) error { Before: func(ctx *cli.Context) error {
// we require either domains or csr, but not both // we require either domains or csr, but not both
hasDomains := len(ctx.GlobalStringSlice("domains")) > 0 hasDomains := len(ctx.StringSlice("domains")) > 0
hasCsr := len(ctx.GlobalString("csr")) > 0 hasCsr := len(ctx.String("csr")) > 0
if hasDomains && hasCsr { if hasDomains && hasCsr {
log.Fatal("Please specify either --domains/-d or --csr/-c, but not both") log.Fatal("Please specify either --domains/-d or --csr/-c, but not both")
} }
@ -37,32 +37,32 @@ func createRenew() cli.Command {
return nil return nil
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.IntFlag{ &cli.IntFlag{
Name: "days", Name: "days",
Value: 30, Value: 30,
Usage: "The number of days left on a certificate to renew it.", Usage: "The number of days left on a certificate to renew it.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "reuse-key", Name: "reuse-key",
Usage: "Used to indicate you want to reuse your current private key for the new certificate.", Usage: "Used to indicate you want to reuse your current private key for the new certificate.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "no-bundle", Name: "no-bundle",
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.", Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "must-staple", Name: "must-staple",
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.", Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "renew-hook", Name: "renew-hook",
Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.", Usage: "Define a hook. The hook is executed only when the certificates are effectively renewed.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "preferred-chain", Name: "preferred-chain",
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.", Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "always-deactivate-authorizations", Name: "always-deactivate-authorizations",
Usage: "Force the authorizations to be relinquished even if the certificate request was successful.", Usage: "Force the authorizations to be relinquished even if the certificate request was successful.",
}, },
@ -85,7 +85,7 @@ func renew(ctx *cli.Context) error {
meta := map[string]string{renewEnvAccountEmail: account.Email} meta := map[string]string{renewEnvAccountEmail: account.Email}
// CSR // CSR
if ctx.GlobalIsSet("csr") { if ctx.IsSet("csr") {
return renewForCSR(ctx, client, certsStorage, bundle, meta) return renewForCSR(ctx, client, certsStorage, bundle, meta)
} }
@ -94,7 +94,7 @@ func renew(ctx *cli.Context) error {
} }
func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error { func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
domains := ctx.GlobalStringSlice("domains") domains := ctx.StringSlice("domains")
domain := domains[0] domain := domains[0]
// load the cert resource from files. // load the cert resource from files.
@ -153,7 +153,7 @@ func renewForDomains(ctx *cli.Context, client *lego.Client, certsStorage *Certif
} }
func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error { func renewForCSR(ctx *cli.Context, client *lego.Client, certsStorage *CertificatesStorage, bundle bool, meta map[string]string) error {
csr, err := readCSRFile(ctx.GlobalString("csr")) csr, err := readCSRFile(ctx.String("csr"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View file

@ -3,20 +3,21 @@ package cmd
import ( import (
"github.com/go-acme/lego/v4/acme" "github.com/go-acme/lego/v4/acme"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func createRevoke() cli.Command { func createRevoke() *cli.Command {
return cli.Command{ return &cli.Command{
Name: "revoke", Name: "revoke",
Usage: "Revoke a certificate", Usage: "Revoke a certificate",
Action: revoke, Action: revoke,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "keep, k", Name: "keep",
Aliases: []string{"k"},
Usage: "Keep the certificates after the revocation instead of archiving them.", Usage: "Keep the certificates after the revocation instead of archiving them.",
}, },
cli.UintFlag{ &cli.UintFlag{
Name: "reason", Name: "reason",
Usage: "Identifies the reason for the certificate revocation. See https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1. 0(unspecified),1(keyCompromise),2(cACompromise),3(affiliationChanged),4(superseded),5(cessationOfOperation),6(certificateHold),8(removeFromCRL),9(privilegeWithdrawn),10(aACompromise)", Usage: "Identifies the reason for the certificate revocation. See https://www.rfc-editor.org/rfc/rfc5280.html#section-5.3.1. 0(unspecified),1(keyCompromise),2(cACompromise),3(affiliationChanged),4(superseded),5(cessationOfOperation),6(certificateHold),8(removeFromCRL),9(privilegeWithdrawn),10(aACompromise)",
Value: acme.CRLReasonUnspecified, Value: acme.CRLReasonUnspecified,
@ -35,7 +36,7 @@ func revoke(ctx *cli.Context) error {
certsStorage := NewCertificatesStorage(ctx) certsStorage := NewCertificatesStorage(ctx)
certsStorage.CreateRootFolder() certsStorage.CreateRootFolder()
for _, domain := range ctx.GlobalStringSlice("domains") { for _, domain := range ctx.StringSlice("domains") {
log.Printf("Trying to revoke certificate for domain %s", domain) log.Printf("Trying to revoke certificate for domain %s", domain)
certBytes, err := certsStorage.ReadFile(domain, ".crt") certBytes, err := certsStorage.ReadFile(domain, ".crt")

View file

@ -10,17 +10,17 @@ import (
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func createRun() cli.Command { func createRun() *cli.Command {
return cli.Command{ return &cli.Command{
Name: "run", Name: "run",
Usage: "Register an account, then create and install a certificate", Usage: "Register an account, then create and install a certificate",
Before: func(ctx *cli.Context) error { Before: func(ctx *cli.Context) error {
// we require either domains or csr, but not both // we require either domains or csr, but not both
hasDomains := len(ctx.GlobalStringSlice("domains")) > 0 hasDomains := len(ctx.StringSlice("domains")) > 0
hasCsr := len(ctx.GlobalString("csr")) > 0 hasCsr := len(ctx.String("csr")) > 0
if hasDomains && hasCsr { if hasDomains && hasCsr {
log.Fatal("Please specify either --domains/-d or --csr/-c, but not both") log.Fatal("Please specify either --domains/-d or --csr/-c, but not both")
} }
@ -31,23 +31,23 @@ func createRun() cli.Command {
}, },
Action: run, Action: run,
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.BoolFlag{ &cli.BoolFlag{
Name: "no-bundle", Name: "no-bundle",
Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.", Usage: "Do not create a certificate bundle by adding the issuers certificate to the new certificate.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "must-staple", Name: "must-staple",
Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.", Usage: "Include the OCSP must staple TLS extension in the CSR and generated certificate. Only works if the CSR is generated by lego.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "run-hook", Name: "run-hook",
Usage: "Define a hook. The hook is executed when the certificates are effectively created.", Usage: "Define a hook. The hook is executed when the certificates are effectively created.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "preferred-chain", Name: "preferred-chain",
Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.", Usage: "If the CA offers multiple certificate chains, prefer the chain with an issuer matching this Subject Common Name. If no match, the default offered chain will be used.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "always-deactivate-authorizations", Name: "always-deactivate-authorizations",
Usage: "Force the authorizations to be relinquished even if the certificate request was successful.", Usage: "Force the authorizations to be relinquished even if the certificate request was successful.",
}, },
@ -110,7 +110,7 @@ func run(ctx *cli.Context) error {
func handleTOS(ctx *cli.Context, client *lego.Client) bool { func handleTOS(ctx *cli.Context, client *lego.Client) bool {
// Check for a global accept override // Check for a global accept override
if ctx.GlobalBool("accept-tos") { if ctx.Bool("accept-tos") {
return true return true
} }
@ -142,9 +142,9 @@ func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, er
log.Fatal("You did not accept the TOS. Unable to proceed.") log.Fatal("You did not accept the TOS. Unable to proceed.")
} }
if ctx.GlobalBool("eab") { if ctx.Bool("eab") {
kid := ctx.GlobalString("kid") kid := ctx.String("kid")
hmacEncoded := ctx.GlobalString("hmac") hmacEncoded := ctx.String("hmac")
if kid == "" || hmacEncoded == "" { if kid == "" || hmacEncoded == "" {
log.Fatalf("Requires arguments --kid and --hmac.") log.Fatalf("Requires arguments --kid and --hmac.")
@ -163,7 +163,7 @@ func register(ctx *cli.Context, client *lego.Client) (*registration.Resource, er
func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Resource, error) { func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Resource, error) {
bundle := !ctx.Bool("no-bundle") bundle := !ctx.Bool("no-bundle")
domains := ctx.GlobalStringSlice("domains") domains := ctx.StringSlice("domains")
if len(domains) > 0 { if len(domains) > 0 {
// obtain a certificate, generating a new private key // obtain a certificate, generating a new private key
request := certificate.ObtainRequest{ request := certificate.ObtainRequest{
@ -177,7 +177,7 @@ func obtainCertificate(ctx *cli.Context, client *lego.Client) (*certificate.Reso
} }
// read the CSR // read the CSR
csr, err := readCSRFile(ctx.GlobalString("csr")) csr, err := readCSRFile(ctx.String("csr"))
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -2,126 +2,132 @@ package cmd
import ( import (
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
pkcs12 "software.sslmate.com/src/go-pkcs12" "software.sslmate.com/src/go-pkcs12"
) )
func CreateFlags(defaultPath string) []cli.Flag { func CreateFlags(defaultPath string) []cli.Flag {
return []cli.Flag{ return []cli.Flag{
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "domains, d", Name: "domains",
Aliases: []string{"d"},
Usage: "Add a domain to the process. Can be specified multiple times.", Usage: "Add a domain to the process. Can be specified multiple times.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "server, s", Name: "server",
Aliases: []string{"s"},
Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.", Usage: "CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client.",
Value: lego.LEDirectoryProduction, Value: lego.LEDirectoryProduction,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "accept-tos, a", Name: "accept-tos",
Aliases: []string{"a"},
Usage: "By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.", Usage: "By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "email, m", Name: "email",
Aliases: []string{"m"},
Usage: "Email used for registration and recovery contact.", Usage: "Email used for registration and recovery contact.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "csr, c", Name: "csr",
Aliases: []string{"c"},
Usage: "Certificate signing request filename, if an external CSR is to be used.", Usage: "Certificate signing request filename, if an external CSR is to be used.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "eab", Name: "eab",
Usage: "Use External Account Binding for account registration. Requires --kid and --hmac.", Usage: "Use External Account Binding for account registration. Requires --kid and --hmac.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "kid", Name: "kid",
Usage: "Key identifier from External CA. Used for External Account Binding.", Usage: "Key identifier from External CA. Used for External Account Binding.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "hmac", Name: "hmac",
Usage: "MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.", Usage: "MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "key-type, k", Name: "key-type",
Aliases: []string{"k"},
Value: "ec256", Value: "ec256",
Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384.", Usage: "Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "filename", Name: "filename",
Usage: "(deprecated) Filename of the generated certificate.", Usage: "(deprecated) Filename of the generated certificate.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "path", Name: "path",
EnvVar: "LEGO_PATH", EnvVars: []string{"LEGO_PATH"},
Usage: "Directory to use for storing the data.", Usage: "Directory to use for storing the data.",
Value: defaultPath, Value: defaultPath,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "http", Name: "http",
Usage: "Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.", Usage: "Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "http.port", Name: "http.port",
Usage: "Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port.", Usage: "Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port.",
Value: ":80", Value: ":80",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "http.proxy-header", Name: "http.proxy-header",
Usage: "Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy.", Usage: "Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy.",
Value: "Host", Value: "Host",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "http.webroot", Name: "http.webroot",
Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge", Usage: "Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "http.memcached-host", Name: "http.memcached-host",
Usage: "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.", Usage: "Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "tls", Name: "tls",
Usage: "Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.", Usage: "Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "tls.port", Name: "tls.port",
Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port.", Usage: "Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port.",
Value: ":443", Value: ":443",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "dns", Name: "dns",
Usage: "Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.", Usage: "Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "dns.disable-cp", Name: "dns.disable-cp",
Usage: "By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.", Usage: "By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.",
}, },
cli.StringSliceFlag{ &cli.StringSliceFlag{
Name: "dns.resolvers", Name: "dns.resolvers",
Usage: "Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.", Usage: "Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.",
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "http-timeout", Name: "http-timeout",
Usage: "Set the HTTP timeout value to a specific value in seconds.", Usage: "Set the HTTP timeout value to a specific value in seconds.",
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "dns-timeout", Name: "dns-timeout",
Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries.", Usage: "Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries.",
Value: 10, Value: 10,
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "pem", Name: "pem",
Usage: "Generate a .pem file by concatenating the .key and .crt files together.", Usage: "Generate a .pem file by concatenating the .key and .crt files together.",
}, },
cli.BoolFlag{ &cli.BoolFlag{
Name: "pfx", Name: "pfx",
Usage: "Generate a .pfx (PKCS#12) file by with the .key and .crt and issuer .crt files together.", Usage: "Generate a .pfx (PKCS#12) file by with the .key and .crt and issuer .crt files together.",
}, },
cli.StringFlag{ &cli.StringFlag{
Name: "pfx.pass", Name: "pfx.pass",
Usage: "The password used to encrypt the .pfx (PCKS#12) file.", Usage: "The password used to encrypt the .pfx (PCKS#12) file.",
Value: pkcs12.DefaultPassword, Value: pkcs12.DefaultPassword,
}, },
cli.IntFlag{ &cli.IntFlag{
Name: "cert.timeout", Name: "cert.timeout",
Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.", Usage: "Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates.",
Value: 30, Value: 30,

View file

@ -10,7 +10,7 @@ import (
"github.com/go-acme/lego/v4/cmd" "github.com/go-acme/lego/v4/cmd"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
var version = "dev" var version = "dev"

View file

@ -12,7 +12,7 @@ import (
"github.com/go-acme/lego/v4/lego" "github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/log" "github.com/go-acme/lego/v4/log"
"github.com/go-acme/lego/v4/registration" "github.com/go-acme/lego/v4/registration"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const filePerm os.FileMode = 0o600 const filePerm os.FileMode = 0o600
@ -35,16 +35,16 @@ func setup(ctx *cli.Context, accountsStorage *AccountsStorage) (*Account, *lego.
func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyType) *lego.Client { func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyType) *lego.Client {
config := lego.NewConfig(acc) config := lego.NewConfig(acc)
config.CADirURL = ctx.GlobalString("server") config.CADirURL = ctx.String("server")
config.Certificate = lego.CertificateConfig{ config.Certificate = lego.CertificateConfig{
KeyType: keyType, KeyType: keyType,
Timeout: time.Duration(ctx.GlobalInt("cert.timeout")) * time.Second, Timeout: time.Duration(ctx.Int("cert.timeout")) * time.Second,
} }
config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version) config.UserAgent = fmt.Sprintf("lego-cli/%s", ctx.App.Version)
if ctx.GlobalIsSet("http-timeout") { if ctx.IsSet("http-timeout") {
config.HTTPClient.Timeout = time.Duration(ctx.GlobalInt("http-timeout")) * time.Second config.HTTPClient.Timeout = time.Duration(ctx.Int("http-timeout")) * time.Second
} }
client, err := lego.NewClient(config) client, err := lego.NewClient(config)
@ -52,7 +52,7 @@ func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyTy
log.Fatalf("Could not create client: %v", err) log.Fatalf("Could not create client: %v", err)
} }
if client.GetExternalAccountRequired() && !ctx.GlobalIsSet("eab") { if client.GetExternalAccountRequired() && !ctx.IsSet("eab") {
log.Fatal("Server requires External Account Binding. Use --eab with --kid and --hmac.") log.Fatal("Server requires External Account Binding. Use --eab with --kid and --hmac.")
} }
@ -61,7 +61,7 @@ func newClient(ctx *cli.Context, acc registration.User, keyType certcrypto.KeyTy
// getKeyType the type from which private keys should be generated. // getKeyType the type from which private keys should be generated.
func getKeyType(ctx *cli.Context) certcrypto.KeyType { func getKeyType(ctx *cli.Context) certcrypto.KeyType {
keyType := ctx.GlobalString("key-type") keyType := ctx.String("key-type")
switch strings.ToUpper(keyType) { switch strings.ToUpper(keyType) {
case "RSA2048": case "RSA2048":
return certcrypto.RSA2048 return certcrypto.RSA2048
@ -80,7 +80,7 @@ func getKeyType(ctx *cli.Context) certcrypto.KeyType {
} }
func getEmail(ctx *cli.Context) string { func getEmail(ctx *cli.Context) string {
email := ctx.GlobalString("email") email := ctx.String("email")
if email == "" { if email == "" {
log.Fatal("You have to pass an account (email address) to the program using --email or -m") log.Fatal("You have to pass an account (email address) to the program using --email or -m")
} }

View file

@ -14,49 +14,49 @@ import (
"github.com/go-acme/lego/v4/providers/dns" "github.com/go-acme/lego/v4/providers/dns"
"github.com/go-acme/lego/v4/providers/http/memcached" "github.com/go-acme/lego/v4/providers/http/memcached"
"github.com/go-acme/lego/v4/providers/http/webroot" "github.com/go-acme/lego/v4/providers/http/webroot"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
func setupChallenges(ctx *cli.Context, client *lego.Client) { func setupChallenges(ctx *cli.Context, client *lego.Client) {
if !ctx.GlobalBool("http") && !ctx.GlobalBool("tls") && !ctx.GlobalIsSet("dns") { if !ctx.Bool("http") && !ctx.Bool("tls") && !ctx.IsSet("dns") {
log.Fatal("No challenge selected. You must specify at least one challenge: `--http`, `--tls`, `--dns`.") log.Fatal("No challenge selected. You must specify at least one challenge: `--http`, `--tls`, `--dns`.")
} }
if ctx.GlobalBool("http") { if ctx.Bool("http") {
err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx)) err := client.Challenge.SetHTTP01Provider(setupHTTPProvider(ctx))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
if ctx.GlobalBool("tls") { if ctx.Bool("tls") {
err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx)) err := client.Challenge.SetTLSALPN01Provider(setupTLSProvider(ctx))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
if ctx.GlobalIsSet("dns") { if ctx.IsSet("dns") {
setupDNS(ctx, client) setupDNS(ctx, client)
} }
} }
func setupHTTPProvider(ctx *cli.Context) challenge.Provider { func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
switch { switch {
case ctx.GlobalIsSet("http.webroot"): case ctx.IsSet("http.webroot"):
ps, err := webroot.NewHTTPProvider(ctx.GlobalString("http.webroot")) ps, err := webroot.NewHTTPProvider(ctx.String("http.webroot"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
return ps return ps
case ctx.GlobalIsSet("http.memcached-host"): case ctx.IsSet("http.memcached-host"):
ps, err := memcached.NewMemcachedProvider(ctx.GlobalStringSlice("http.memcached-host")) ps, err := memcached.NewMemcachedProvider(ctx.StringSlice("http.memcached-host"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
return ps return ps
case ctx.GlobalIsSet("http.port"): case ctx.IsSet("http.port"):
iface := ctx.GlobalString("http.port") iface := ctx.String("http.port")
if !strings.Contains(iface, ":") { if !strings.Contains(iface, ":") {
log.Fatalf("The --http switch only accepts interface:port or :port for its argument.") log.Fatalf("The --http switch only accepts interface:port or :port for its argument.")
} }
@ -67,13 +67,13 @@ func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
} }
srv := http01.NewProviderServer(host, port) srv := http01.NewProviderServer(host, port)
if header := ctx.GlobalString("http.proxy-header"); header != "" { if header := ctx.String("http.proxy-header"); header != "" {
srv.SetProxyHeader(header) srv.SetProxyHeader(header)
} }
return srv return srv
case ctx.GlobalBool("http"): case ctx.Bool("http"):
srv := http01.NewProviderServer("", "") srv := http01.NewProviderServer("", "")
if header := ctx.GlobalString("http.proxy-header"); header != "" { if header := ctx.String("http.proxy-header"); header != "" {
srv.SetProxyHeader(header) srv.SetProxyHeader(header)
} }
return srv return srv
@ -85,8 +85,8 @@ func setupHTTPProvider(ctx *cli.Context) challenge.Provider {
func setupTLSProvider(ctx *cli.Context) challenge.Provider { func setupTLSProvider(ctx *cli.Context) challenge.Provider {
switch { switch {
case ctx.GlobalIsSet("tls.port"): case ctx.IsSet("tls.port"):
iface := ctx.GlobalString("tls.port") iface := ctx.String("tls.port")
if !strings.Contains(iface, ":") { if !strings.Contains(iface, ":") {
log.Fatalf("The --tls switch only accepts interface:port or :port for its argument.") log.Fatalf("The --tls switch only accepts interface:port or :port for its argument.")
} }
@ -97,7 +97,7 @@ func setupTLSProvider(ctx *cli.Context) challenge.Provider {
} }
return tlsalpn01.NewProviderServer(host, port) return tlsalpn01.NewProviderServer(host, port)
case ctx.GlobalBool("tls"): case ctx.Bool("tls"):
return tlsalpn01.NewProviderServer("", "") return tlsalpn01.NewProviderServer("", "")
default: default:
log.Fatal("Invalid HTTP challenge options.") log.Fatal("Invalid HTTP challenge options.")
@ -106,19 +106,19 @@ func setupTLSProvider(ctx *cli.Context) challenge.Provider {
} }
func setupDNS(ctx *cli.Context, client *lego.Client) { func setupDNS(ctx *cli.Context, client *lego.Client) {
provider, err := dns.NewDNSChallengeProviderByName(ctx.GlobalString("dns")) provider, err := dns.NewDNSChallengeProviderByName(ctx.String("dns"))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
servers := ctx.GlobalStringSlice("dns.resolvers") servers := ctx.StringSlice("dns.resolvers")
err = client.Challenge.SetDNS01Provider(provider, err = client.Challenge.SetDNS01Provider(provider,
dns01.CondOption(len(servers) > 0, dns01.CondOption(len(servers) > 0,
dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.GlobalStringSlice("dns.resolvers")))), dns01.AddRecursiveNameservers(dns01.ParseNameservers(ctx.StringSlice("dns.resolvers")))),
dns01.CondOption(ctx.GlobalBool("dns.disable-cp"), dns01.CondOption(ctx.Bool("dns.disable-cp"),
dns01.DisableCompletePropagationRequirement()), dns01.DisableCompletePropagationRequirement()),
dns01.CondOption(ctx.GlobalIsSet("dns-timeout"), dns01.CondOption(ctx.IsSet("dns-timeout"),
dns01.AddDNSTimeout(time.Duration(ctx.GlobalInt("dns-timeout"))*time.Second)), dns01.AddDNSTimeout(time.Duration(ctx.Int("dns-timeout"))*time.Second)),
) )
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View file

@ -28,33 +28,33 @@ COMMANDS:
GLOBAL OPTIONS: GLOBAL OPTIONS:
--domains value, -d value Add a domain to the process. Can be specified multiple times. --domains value, -d value Add a domain to the process. Can be specified multiple times.
--server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory") --server value, -s value CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory")
--accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service. --accept-tos, -a By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service. (default: false)
--email value, -m value Email used for registration and recovery contact. --email value, -m value Email used for registration and recovery contact.
--csr value, -c value Certificate signing request filename, if an external CSR is to be used. --csr value, -c value Certificate signing request filename, if an external CSR is to be used.
--eab Use External Account Binding for account registration. Requires --kid and --hmac. --eab Use External Account Binding for account registration. Requires --kid and --hmac. (default: false)
--kid value Key identifier from External CA. Used for External Account Binding. --kid value Key identifier from External CA. Used for External Account Binding.
--hmac value MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding. --hmac value MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.
--key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec256") --key-type value, -k value Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec256")
--filename value (deprecated) Filename of the generated certificate. --filename value (deprecated) Filename of the generated certificate.
--path value Directory to use for storing the data. (default: "./.lego") [$LEGO_PATH] --path value Directory to use for storing the data. (default: "./.lego") [$LEGO_PATH]
--http Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges. --http Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges. (default: false)
--http.port value Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80") --http.port value Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80")
--http.proxy-header value Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host") --http.proxy-header value Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host")
--http.webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge --http.webroot value Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge
--http.memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts. --http.memcached-host value Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
--tls Use the TLS challenge to solve challenges. Can be mixed with other types of challenges. --tls Use the TLS challenge to solve challenges. Can be mixed with other types of challenges. (default: false)
--tls.port value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443") --tls.port value Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443")
--dns value Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage. --dns value Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.
--dns.disable-cp By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers. --dns.disable-cp By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers. (default: false)
--dns.resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined. --dns.resolvers value Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.
--http-timeout value Set the HTTP timeout value to a specific value in seconds. (default: 0) --http-timeout value Set the HTTP timeout value to a specific value in seconds. (default: 0)
--dns-timeout value Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10) --dns-timeout value Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10)
--pem Generate a .pem file by concatenating the .key and .crt files together. --pem Generate a .pem file by concatenating the .key and .crt files together. (default: false)
--pfx Generate a .pfx (PKCS#12) file by with the .key and .crt and issuer .crt files together. --pfx Generate a .pfx (PKCS#12) file by with the .key and .crt and issuer .crt files together. (default: false)
--pfx.pass The password used to encrypt the .pfx (PCKS#12) file (default: changeit). --pfx.pass value The password used to encrypt the .pfx (PCKS#12) file. (default: "changeit")
--cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30) --cert.timeout value Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
--help, -h show help --help, -h show help (default: false)
--version, -v print the version --version, -v print the version (default: false)
``` ```
When using the standard `--path` option, all certificates and account configurations are saved to a folder `.lego` in the current working directory. When using the standard `--path` option, all certificates and account configurations are saved to a folder `.lego` in the current working directory.

2
go.mod
View file

@ -52,7 +52,7 @@ require (
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287 github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287
github.com/transip/gotransip/v6 v6.6.1 github.com/transip/gotransip/v6 v6.6.1
github.com/urfave/cli v1.22.5 github.com/urfave/cli/v2 v2.3.0
github.com/vinyldns/go-vinyldns v0.9.16 github.com/vinyldns/go-vinyldns v0.9.16
github.com/vultr/govultr/v2 v2.7.1 github.com/vultr/govultr/v2 v2.7.1
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e

3
go.sum
View file

@ -474,8 +474,7 @@ github.com/transip/gotransip/v6 v6.6.1 h1:nsCU1ErZS5G0FeOpgGXc4FsWvBff9GPswSMggs
github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g= github.com/transip/gotransip/v6 v6.6.1/go.mod h1:pQZ36hWWRahCUXkFWlx9Hs711gLd8J4qdgLdRzmtY+g=
github.com/uber-go/atomic v1.3.2 h1:Azu9lPBWRNKzYXSIwRfgRuDuS0YKsK4NFhiQv98gkxo= github.com/uber-go/atomic v1.3.2 h1:Azu9lPBWRNKzYXSIwRfgRuDuS0YKsK4NFhiQv98gkxo=
github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g=
github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=

View file

@ -14,7 +14,7 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/urfave/cli" "github.com/urfave/cli/v2"
) )
const sourceFile = "./acme/api/internal/sender/useragent.go" const sourceFile = "./acme/api/internal/sender/useragent.go"
@ -41,7 +41,7 @@ func main() {
app.Name = "lego-releaser" app.Name = "lego-releaser"
app.Usage = "Lego releaser" app.Usage = "Lego releaser"
app.HelpName = "releaser" app.HelpName = "releaser"
app.Commands = []cli.Command{ app.Commands = []*cli.Command{
{ {
Name: "release", Name: "release",
Usage: "Update file for a release", Usage: "Update file for a release",
@ -56,8 +56,9 @@ func main() {
} }
}, },
Flags: []cli.Flag{ Flags: []cli.Flag{
cli.StringFlag{ &cli.StringFlag{
Name: "mode, m", Name: "mode",
Aliases: []string{"m"},
Value: "patch", Value: "patch",
Usage: "The release mode: patch|minor|major", Usage: "The release mode: patch|minor|major",
}, },