posh-providers/filosottile/mkcert/command.go
Kevin Franklin Kim f9240e6d72
feat: add mkcert
2023-12-05 14:03:55 +01:00

203 lines
5.1 KiB
Go

package mkcert
import (
"context"
"fmt"
"github.com/foomo/posh/pkg/command/tree"
"github.com/foomo/posh/pkg/log"
"github.com/foomo/posh/pkg/prompt/goprompt"
"github.com/foomo/posh/pkg/readline"
"github.com/foomo/posh/pkg/shell"
"github.com/foomo/posh/pkg/util/files"
"github.com/pkg/errors"
"github.com/spf13/viper"
)
type (
Command struct {
l log.Logger
cfg Config
name string
configKey string
commandTree tree.Root
}
Option func(*Command) error
)
// ------------------------------------------------------------------------------------------------
// ~ Options
// ------------------------------------------------------------------------------------------------
func CommandWithName(v string) Option {
return func(o *Command) error {
o.name = v
return nil
}
}
func WithConfigKey(v string) Option {
return func(o *Command) error {
o.configKey = v
return nil
}
}
// ------------------------------------------------------------------------------------------------
// ~ Constructor
// ------------------------------------------------------------------------------------------------
func NewCommand(l log.Logger, opts ...Option) (*Command, error) {
inst := &Command{
l: l.Named("mkcert"),
name: "mkcert",
configKey: "mkcert",
}
for _, opt := range opts {
if opt != nil {
if err := opt(inst); err != nil {
return nil, err
}
}
}
if err := viper.UnmarshalKey(inst.configKey, &inst.cfg); err != nil {
return nil, err
}
inst.commandTree = tree.New(&tree.Node{
Name: inst.name,
Description: "Run mkcert",
Nodes: tree.Nodes{
{
Name: "install",
Description: "Install the local CA in the system trust store",
Execute: inst.install,
},
{
Name: "caroot",
Description: "Print the CA certificate and key storage location",
Execute: inst.caroot,
},
{
Name: "uninstall",
Description: "Uninstall the local CA (but do not delete it)",
Execute: inst.uninstall,
},
{
Name: "generate",
Description: "Generate configured certificates",
Execute: inst.generate,
},
{
Name: "create",
Description: "Creat a new certificate for the given names",
Args: []*tree.Arg{
{
Name: "names",
Description: "List of names including wildcard",
Repeat: true,
},
},
Execute: inst.create,
},
},
})
return inst, nil
}
// ------------------------------------------------------------------------------------------------
// ~ Public methods
// ------------------------------------------------------------------------------------------------
func (c *Command) Name() string {
return c.commandTree.Node().Name
}
func (c *Command) Description() string {
return c.commandTree.Node().Description
}
func (c *Command) Complete(ctx context.Context, r *readline.Readline) []goprompt.Suggest {
return c.commandTree.Complete(ctx, r)
}
func (c *Command) Validate(ctx context.Context, r *readline.Readline) error {
switch {
case r.Args().LenIs(0):
return errors.New("missing [CMD] argument")
}
return nil
}
func (c *Command) Execute(ctx context.Context, r *readline.Readline) error {
return c.commandTree.Execute(ctx, r)
}
func (c *Command) Help(ctx context.Context, r *readline.Readline) string {
return c.commandTree.Help(ctx, r)
}
// ------------------------------------------------------------------------------------------------
// ~ Private methods
// ------------------------------------------------------------------------------------------------
func (c *Command) install(ctx context.Context, r *readline.Readline) error {
return shell.New(ctx, c.l, "mkcert", "-install").
Args(r.Args()...).
Args(r.Flags()...).
Args(r.AdditionalArgs()...).
Run()
}
func (c *Command) generate(ctx context.Context, r *readline.Readline) error {
if err := files.MkdirAll(c.cfg.CertificatePath); err != nil {
return err
}
c.l.Info("Generating certificates:")
for _, certificate := range c.cfg.Certificates {
c.l.Info("└ " + certificate.Name)
if err := shell.New(ctx, c.l, "mkcert").
Args("-key-file", fmt.Sprintf("%s-key.pem", certificate.Name)).
Args("-cert-file", fmt.Sprintf("%s.pem", certificate.Name)).
Dir(c.cfg.CertificatePath).
Args(certificate.Names...).
Args(r.Flags()...).
Args(r.AdditionalArgs()...).
Run(); err != nil {
return err
}
}
return nil
}
func (c *Command) caroot(ctx context.Context, r *readline.Readline) error {
return shell.New(ctx, c.l, "mkcert", "-CAROOT").
Args(r.Args()...).
Args(r.Flags()...).
Args(r.AdditionalArgs()...).
Run()
}
func (c *Command) uninstall(ctx context.Context, r *readline.Readline) error {
return shell.New(ctx, c.l, "mkcert", "-uninstall").
Args(r.Args()...).
Args(r.Flags()...).
Args(r.AdditionalArgs()...).
Run()
}
func (c *Command) create(ctx context.Context, r *readline.Readline) error {
if err := files.MkdirAll(c.cfg.CertificatePath); err != nil {
return err
}
return shell.New(ctx, c.l, "mkcert").
Dir(c.cfg.CertificatePath).
Args(r.Args().From(1)...).
Args(r.Flags()...).
Args(r.AdditionalArgs()...).
Run()
}