command

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2023 License: MIT Imports: 37 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var Configure = cli.Command{
	Name:  "configure",
	Usage: "Update or create .env file with all the required configuration fields",
	Flags: []cli.Flag{},
	Action: func(c *cli.Context) error {
		var out bytes.Buffer
		cmd := exec.Command(".venv/bin/provider", "schema")
		cmd.Stderr = os.Stderr
		cmd.Stdout = &out
		err := cmd.Run()
		if err != nil {
			return err
		}

		var schema providerregistrysdk.Schema
		err = json.Unmarshal(out.Bytes(), &schema)
		if err != nil {
			return err
		}

		values := make(map[string]string)

		if schema.Config == nil {

			return nil
		}

		for k, v := range *schema.Config {
			// prompt the user for each config value
			var ans string
			err = survey.AskOne(&survey.Input{Message: k + ":"}, &ans)
			if err != nil {
				return err
			}

			if v.Secret != nil && *v.Secret {
				values["PROVIDER_SECRET_"+strings.ToUpper(k)] = ans
			} else {
				values["PROVIDER_CONFIG_"+strings.ToUpper(k)] = ans
			}
		}

		err = godotenv.Write(values, ".env")
		if err != nil {
			return err
		}

		return nil
	},
}
View Source
var CreatePublisherCommand = cli.Command{
	Name:  "create",
	Usage: "Create a publisher",
	Flags: []cli.Flag{
		&cli.StringFlag{Name: "id"},
	},
	Action: func(c *cli.Context) error {
		ctx := c.Context
		registryclient, err := client.NewWithAuthToken(ctx)
		if err != nil {
			return err
		}
		id := c.String("id")
		if id == "" {
			err = survey.AskOne(&survey.Input{Message: "Publisher ID"}, &id)
			if err != nil {
				return err
			}
		}
		_, err = registryclient.UserCreatePublisher(ctx, providerregistrysdk.UserCreatePublisherJSONRequestBody{
			Id: id,
		})
		if err != nil {
			return err
		}
		clio.Successf("Successfully created publisher")

		return nil
	},
}
View Source
var Init = cli.Command{
	Name:  "init",
	Usage: "Scaffold a template for an Access Provider",
	Flags: []cli.Flag{
		&cli.StringFlag{
			Name:    "name",
			Aliases: []string{"n"},
			Usage:   "Provider name",
		},
		&cli.StringFlag{
			Name:    "publisher",
			Aliases: []string{"p"},
			Usage:   "Provider publisher",
		},
		&cli.StringFlag{
			Name:    "template",
			Aliases: []string{"t"},
			Usage:   "The Provider template to use",
			Value:   "basic",
		},
		&cli.StringFlag{
			Name:    "version",
			Aliases: []string{"v"},
			Usage:   "Initial version for the Provider",
			Value:   "v0.1.0",
		},
		&cli.BoolFlag{
			Name:  "create-folder",
			Usage: "Create a new folder for the Provider",
		},
	},
	Action: func(c *cli.Context) error {
		name := c.String("name")
		publisher := c.String("publisher")
		version := c.String("version")
		shouldCreateFolder := c.Bool("create-folder")

		files, err := os.ReadDir(".")
		if err != nil {
			return err
		}

		dir, err := os.Getwd()
		if err != nil {
			return err
		}

		if len(files) != 0 && !shouldCreateFolder {
			clio.Errorf("you are running `pdk init` in a non-empty directory! %s", dir)
			clio.Info("You need to pass `pdk init --create-folder` to create a new Provider repository")

			return nil
		}

		if name == "" {
			in := &survey.Input{
				Message: "Provider name",
				Default: strings.TrimPrefix(path.Base(dir), "cf-provider-"),
			}
			err = survey.AskOne(in, &name)
			if err != nil {
				return err
			}
		}

		if publisher == "" {
			in := &survey.Input{
				Message: "Provider publisher",
				Help:    "This should match the GitHub organization, or your personal GitHub name",
			}
			err = survey.AskOne(in, &publisher)
			if err != nil {
				return err
			}
		}

		templateFlag := c.String("template")

		data := TemplateData{
			PackageName: "provider_" + strings.ReplaceAll(name, "-", "_"),
			Name:        name,
			Publisher:   publisher,
			Version:     version,
		}

		boilerplates, err := boilermaker.ParseMapFS(boilerplate.TemplateFiles, "templates")
		if err != nil {
			return err
		}

		boilerplate, ok := boilerplates[templateFlag]
		if !ok {
			var availableTemplates []string

			for k := range boilerplates {
				availableTemplates = append(availableTemplates, k)
			}

			return fmt.Errorf("invalid template %s. available templates: %s", templateFlag, strings.Join(availableTemplates, ", "))
		}

		result, err := boilerplate.Generate(data)
		if err != nil {
			return err
		}

		if shouldCreateFolder {
			dir = path.Join(dir, "cf-provider-"+data.Name)
			_, err = os.Stat(dir)
			if err != nil {
				if os.IsNotExist(err) {
					err := os.MkdirAll(dir, 0777)
					if err != nil {
						return err
					}
				} else {
					return err
				}
			}
		}

		for f, contents := range result {
			fullpath := filepath.Join(dir, f)
			parent := filepath.Dir(fullpath)
			err := os.MkdirAll(parent, 0755)
			if err != nil {
				return err
			}

			err = os.WriteFile(fullpath, []byte(contents), 0644)
			if err != nil {
				return err
			}
			clio.Infof("created %s", fullpath)
		}

		err = createPyVenv(dir)
		if err != nil {
			return fmt.Errorf("creating python venv err: %s", err)
		}

		clio.Info("Generating virtual environment for python & installing Packages.")

		err = installPythonDependencies(dir)
		if err != nil {
			return err
		}

		clio.Success("Success! Scaffolded a new Common Fate Provider")
		clio.Info("Get started by running these commands next:")
		fmt.Println("source .venv/bin/activate")
		fmt.Println("pdk run describe")
		return nil
	},
}
View Source
var Invoke = cli.Command{
	Name: "invoke",
	Subcommands: []*cli.Command{
		&invokeGrant,
		&invokeRevoke,
		&invokeSchema,
	},
}
View Source
var Login = cli.Command{
	Name:  "login",
	Usage: "Login to Common Fate Provider Registry",
	Flags: []cli.Flag{},
	Action: func(c *cli.Context) error {
		ctx := c.Context

		authResponse := make(chan cliauth.Response)
		authServer := cliauth.Server{
			Response: authResponse,
		}

		server := &http.Server{
			Addr:    ":8848",
			Handler: authServer.Handler(),
		}

		var g errgroup.Group

		g.Go(func() error {
			clio.Debugw("starting HTTP server", "address", server.Addr)
			if err := server.ListenAndServe(); err != http.ErrServerClosed {
				return err
			}
			clio.Debugw("auth server closed")
			return nil
		})

		g.Go(func() error {
			url := "http://localhost:8848/oauth/login"
			clio.Infof("Opening your web browser to: %s", url)
			err := browser.OpenURL(url)
			if err != nil {
				clio.Errorf("error opening browser: %s", err)
			}
			return nil
		})

		g.Go(func() error {
			res := <-authResponse

			err := server.Shutdown(ctx)
			if err != nil {
				return err
			}

			if res.Err != nil {
				return err
			}

			ts := tokenstore.New()
			err = ts.Save(res.Token)
			if err != nil {
				return err
			}

			clio.Successf("logged in")

			return nil
		})

		err := g.Wait()
		if err != nil {
			return err
		}

		return nil
	},
}
View Source
var Logout = cli.Command{
	Name:  "logout",
	Usage: "Log out of Common Fate Provider Registry",
	Action: func(c *cli.Context) error {
		ts := tokenstore.New()
		err := ts.Clear()
		if err != nil {
			return err
		}

		clio.Success("logged out")

		return nil
	},
}
View Source
var Package = cli.Command{
	Name: "package",
	Flags: []cli.Flag{
		&cli.PathFlag{Name: "path", Value: ".", Usage: "The path to the folder containing your provider code e.g ./cf-provider-example"},
		&cli.StringSliceFlag{Name: "local-dependency", Usage: "(For development use) Add a local python package to the zip archive, e.g. provider=../provider/provider"},
	},
	Action: func(c *cli.Context) error {
		ctx := c.Context
		providerPath := c.Path("path")

		localDependency := c.StringSlice("local-dependency")

		err := PackageAndZip(ctx, providerPath, PackageFlagOpts{
			LocalDependency: localDependency,
		})
		if err != nil {
			return err
		}

		return nil
	},
}
View Source
var PublishCommand = cli.Command{
	Name:  "publish",
	Usage: "Publish will package and upload the provider in the provided path argument",
	Flags: []cli.Flag{
		&cli.PathFlag{Name: "path", Value: ".", Usage: "The path to the folder containing your provider code e.g ./cf-provider-example"},
		&cli.BoolFlag{Hidden: true, Name: "dev", Usage: "Pass this flag to hide provider from production registry"},
		&cli.StringSliceFlag{Name: "local-dependency", Usage: "(For development use) Add a local python package to the zip archive, e.g. commonfate_provider=../commonfate-provider-core/commonfate_provider"},
	},
	Action: func(c *cli.Context) error {
		ctx := c.Context

		providerPath := c.Path("path")

		clio.Debugf("packaging a provider in path %s", providerPath)

		err := PackageAndZip(ctx, providerPath, PackageFlagOpts{
			LocalDependency: c.StringSlice("local-dependency"),
		})
		if err != nil {
			return err
		}

		err = UploadProvider(ctx, providerPath, UploadFlagOpts{

			Dev: c.Bool("dev"),
		})
		if err != nil {
			return err
		}

		return nil
	},
}
View Source
var PublisherCommand = cli.Command{
	Name:        "publisher",
	Usage:       "Manage publishers",
	Subcommands: []*cli.Command{&CreatePublisherCommand},
}
View Source
var SchemaCommand = cli.Command{
	Name:  "schema",
	Usage: "Print the schema of the provider in the current folder",
	Action: func(c *cli.Context) error {
		cmd := exec.Command(".venv/bin/provider", "schema")
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		cmd.Stdin = os.Stdin
		return cmd.Run()
	},
}
View Source
var UploadCommand = cli.Command{
	Name:  "upload",
	Usage: "Upload a provider to the registry",
	Flags: []cli.Flag{
		&cli.PathFlag{Name: "path", Value: ".", Usage: "The path to the folder containing your provider code e.g ./cf-provider-example"},
		&cli.BoolFlag{Hidden: true, Name: "dev", Usage: "Pass this flag to hide provider from production registry"},
	},
	Action: func(c *cli.Context) error {
		ctx := c.Context
		providerPath := c.Path("path")
		err := UploadProvider(ctx, providerPath, UploadFlagOpts{
			Dev: c.Bool("dev"),
		})
		if err != nil {
			return err
		}
		return nil
	},
}

Functions

func CheckFilesExist

func CheckFilesExist(providerPath string) error

CheckFilesExist is used to assert that the required files exist prior to starting a publish workflow

func DetectRoleTemplateFiles

func DetectRoleTemplateFiles(roleTemplateFolder string) ([]string, error)

DetectRoleTemplateFiles will look for files in the roles folder which have the .json extension

func PackageAndZip

func PackageAndZip(ctx context.Context, providerPath string, flagOpts PackageFlagOpts) error

func PackageProvider

func PackageProvider(opts PackageProviderOpts) error

PackageProvider creates a zip archive bundle for the provider.

func UploadProvider

func UploadProvider(ctx context.Context, providerPath string, flagOpts UploadFlagOpts) error

func VerifyUserBelongsToPublisher

func VerifyUserBelongsToPublisher(ctx context.Context, publisher string) error

Types

type AddToZipOpts

type AddToZipOpts struct {
	Writer    *zip.Writer
	PathToZip string
	Ignore    *ignore.GitIgnore

	OnlyTheseExtensions []string

	// ZippedPathPrefix sets a prefix to the path in the zip file if specified.
	ZippedPathPrefix string

	// TrimPrefix trims the file prefix,
	// e.g. pythondeps/packagename -> packagename
	TrimPrefix string
}

type Data

type Data struct {
	Subject string `json:"subject"`
	Args    any    `json:"args"`
}

type PackageFlagOpts

type PackageFlagOpts struct {
	LocalDependency []string
}

type PackageProviderOpts

type PackageProviderOpts struct {
	ProviderPath      string
	OutputPath        string
	Provider          Provider
	LocalDependencies []localDependency
}

type Paths

type Paths struct {
	ProviderPath string
}

func (Paths) CloudformationTemplate

func (p Paths) CloudformationTemplate() string

func (Paths) Handler

func (p Paths) Handler() string

func (Paths) Readme

func (p Paths) Readme() string

func (Paths) RoleTemplate

func (p Paths) RoleTemplate(role string) string

func (Paths) RoleTemplateFolder

func (p Paths) RoleTemplateFolder() string

func (Paths) Schema

func (p Paths) Schema() string

type Payload

type Payload struct {
	Type string `json:"type"`
	Data Data   `json:"data"`
}

type Provider

type Provider struct {
	Publisher     string `json:"publisher"`
	Name          string `json:"name"`
	Version       string `json:"version"`
	SchemaVersion string `json:"schema_version"`
	PythonPackage string `json:"python_package"`
}

func (Provider) String

func (p Provider) String() string

type TemplateData added in v0.3.0

type TemplateData struct {
	// PackageName is the name of the Python package folder to create
	PackageName string
	Name        string
	Publisher   string
	Version     string
}

type UploadFlagOpts

type UploadFlagOpts struct {
	Dev bool
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL