private

package
v0.28.6 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2023 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BundleCmd = &cobra.Command{
	Use:     "bundle",
	Short:   "Creates a new app bundle",
	Example: `  pixlet bundle ./my-app`,
	Long: `This command will create a new app bundle from an app directory. The directory
should contain an app manifest and source file. The output of this command will
be a gzip compressed tar file that can be uploaded to Tidbyt for deployment.`,
	Args: cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		bundleInput := args[0]
		info, err := os.Stat(bundleInput)
		if err != nil {
			return fmt.Errorf("input directory invalid: %w", err)
		}

		if !info.IsDir() {
			return fmt.Errorf("input must be a directory")
		}

		info, err = os.Stat(bundleOutput)
		if err != nil {
			return fmt.Errorf("output directory invalid: %w", err)
		}

		if !info.IsDir() {
			return fmt.Errorf("output must be a directory")
		}

		ab, err := bundle.InitFromPath(bundleInput)
		if err != nil {
			return fmt.Errorf("could not init bundle: %w", err)
		}

		return ab.WriteBundleToPath(bundleOutput)
	},
}
View Source
var CreateCmd = &cobra.Command{
	Use:   "create",
	Short: "Creates a new app",
	Long:  `This command will prompt for all of the information we need to generate a new Tidbyt app. No flags are necessary unless you are creating a private app, which is only available with our Tidbyt For Teams offering.`,
	RunE: func(cmd *cobra.Command, args []string) error {

		cwd, err := os.Getwd()
		if err != nil {
			return fmt.Errorf("app creation failed, something went wrong with your local filesystem: %w", err)
		}

		// Determine what type of app this is an what the root should be.
		var root string
		var appType generator.AppType
		if repo.IsInRepo(cwd, "community") {
			appType = generator.Community
			root, err = repo.RepoRoot(cwd)
			if err != nil {
				return fmt.Errorf("app creation failed, something went wrong with your community repo: %w", err)
			}
		} else if repo.IsInRepo(cwd, "tidbyt") {
			appType = generator.Internal
			root, err = repo.RepoRoot(cwd)
			if err != nil {
				return fmt.Errorf("app creation failed, something went wrong with your tidbyt repo: %w", err)
			}
		} else {
			appType = generator.Local
			root = cwd
		}

		app, err := community.ManifestPrompt()
		if err != nil {
			return fmt.Errorf("app creation, couldn't get user input: %w", err)
		}

		apiToken := config.OAuthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		app.ID, err = createPrivateApp(apiToken, createOrg)
		if err != nil {
			if strings.Contains(err.Error(), "user is not authorized to create apps") {
				return fmt.Errorf("user is not authorized to create apps for organization %s, please reach out to your Tidbyt For Teams account representative to enable this feature for your account", createOrg)
			}

			return fmt.Errorf("remote app creation failed: %w", err)
		}

		g, err := generator.NewGenerator(appType, root)
		if err != nil {
			return fmt.Errorf("app creation failed %w", err)
		}
		absolutePath, err := g.GenerateApp(app)
		if err != nil {
			return fmt.Errorf("app creation failed: %w", err)
		}

		relativePath, err := filepath.Rel(cwd, absolutePath)
		if err != nil {
			return fmt.Errorf("app was created, but we don't know where: %w", err)
		}

		fmt.Println("")
		fmt.Println("App created at:")
		fmt.Printf("\t%s\n", absolutePath)
		fmt.Println("")
		fmt.Println("To start the app, run:")
		fmt.Printf("\tpixlet serve %s\n", relativePath)
		fmt.Println("")
		fmt.Println("For docs, head to:")
		fmt.Printf("\thttps://tidbyt.dev\n")

		fmt.Println("")
		fmt.Println("To deploy your app:")
		fmt.Printf("\tpixlet private bundle ./\n")
		fmt.Printf("\tpixlet private upload bundle.tar.gz --app %s --version v0.0.1\n", app.ID)
		fmt.Printf("\tpixlet private deploy --app %s --version v0.0.1\n", app.ID)

		return nil
	},
}

CreateCmd prompts the user for info and generates a new app.

View Source
var DeleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "Deletes a private app",
	Long:  `Deletes a private app, and attempt to uninstall it from owner's devices.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		apiToken := config.OAuthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		requestURL := fmt.Sprintf("%s/v0/apps/%s", deleteURL, deleteAppID)
		req, err := http.NewRequest("DELETE", requestURL, nil)
		if err != nil {
			return fmt.Errorf("could not create http request: %w", err)
		}

		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiToken))

		client := http.Client{
			Timeout: 10 * time.Second,
		}

		resp, err := client.Do(req)
		if err != nil {
			return fmt.Errorf("could not make HTTP request to %s: %w", requestURL, err)
		}
		defer resp.Body.Close()

		body, err := io.ReadAll(resp.Body)
		if err != nil {
			return fmt.Errorf("could not read response body: %w", err)
		}

		if resp.StatusCode != 200 {
			return fmt.Errorf("request returned status %d with message: %s", resp.StatusCode, body)
		}

		return nil
	},
}
View Source
var DeployCmd = &cobra.Command{
	Use:     "deploy",
	Short:   "Deploys a private app version",
	Example: `  pixlet deploy --app <app-id> --version v0.0.1`,
	Long:    `This command will deploy a private app to the Tidbyt backend.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		apiToken := config.OAuthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		if deployAppID == "" {
			return fmt.Errorf("app must not be blank")
		}

		if deployVersion == "" {
			return fmt.Errorf("version must not be blank")
		}

		d := &TidbytAppDeploy{
			AppID:   deployAppID,
			Version: deployVersion,
		}

		b, err := json.Marshal(d)
		if err != nil {
			return fmt.Errorf("could not create http request: %w", err)
		}

		requestURL := fmt.Sprintf("%s/v0/apps/%s/deploy", deployURL, deployAppID)
		req, err := http.NewRequest(http.MethodPost, requestURL, bytes.NewBuffer(b))
		if err != nil {
			return fmt.Errorf("could not create http request: %w", err)
		}

		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiToken))

		client := http.Client{
			Timeout: 30 * time.Second,
		}

		resp, err := client.Do(req)
		if err != nil {
			return fmt.Errorf("could not make HTTP request to %s: %w", requestURL, err)
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			body, _ := io.ReadAll(resp.Body)
			return fmt.Errorf("request returned status %d with message: %s", resp.StatusCode, body)
		}

		return nil
	},
}
View Source
var ListCmd = &cobra.Command{
	Use:   "list",
	Short: "Lists private apps",
	Long:  `Lists private apps, including team apps.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		apiToken := config.OAuthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		requestURL := fmt.Sprintf("%s/v0/apps", listURL)
		req, err := http.NewRequest("GET", requestURL, nil)
		if err != nil {
			return fmt.Errorf("could not create http request: %w", err)
		}

		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiToken))

		client := http.Client{
			Timeout: 10 * time.Second,
		}

		resp, err := client.Do(req)
		if err != nil {
			return fmt.Errorf("could not make HTTP request to %s: %w", requestURL, err)
		}
		defer resp.Body.Close()

		body, err := io.ReadAll(resp.Body)
		if resp.StatusCode != 200 {
			return fmt.Errorf("request returned status %d with message: %s", resp.StatusCode, body)
		}

		if err != nil {
			return fmt.Errorf("could not read response body: %w", err)
		}

		var apps struct {
			Apps []TidbytApp `json:"apps"`
		}
		err = json.Unmarshal(body, &apps)
		if err != nil {
			return fmt.Errorf("could not parse response body: %w", err)
		}

		for _, app := range apps.Apps {
			if !app.Private {
				continue
			}
			appJson, err := json.Marshal(app)
			if err != nil {
				return fmt.Errorf("could not marshal app: %w", err)
			}
			fmt.Println(string(appJson))
		}

		return nil
	},
}
View Source
var PrivateCmd = &cobra.Command{
	Use:   "private",
	Short: "Utilities to manage private apps",
	Long: `The private subcommand provides a set of utilities for managing
private apps. Requires Tidbyt Plus or Tidbyt for Teams.`,
}
View Source
var UploadCmd = &cobra.Command{
	Use:     "upload",
	Short:   "Uploads an app bundle to Tidbyt (internal only)",
	Example: `  pixlet upload bundle.tar.gz --app fuzzy-clock --version v0.0.1 --token {{ api_token }}`,
	Long: `This command will upload an app bundle (see pixlet bundle) using the specified
app ID and version. Note, this is for internal use only at the moment, and
normal API tokens will not work with this command. We fully intend to make this
command public once our backend is well positioned to support it.`,
	Args: cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		bundleFile := args[0]
		info, err := os.Stat(bundleFile)
		if err != nil {
			return fmt.Errorf("input bundle file invalid: %w", err)
		}

		if info.IsDir() {
			return fmt.Errorf("input bundle must be a file")
		}

		if !strings.HasSuffix(bundleFile, "tar.gz") {
			return fmt.Errorf("input bundle format is not correct, did you create it with `pixlet bundle`?")
		}

		apiToken := config.OAuthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		if uploadAppID == "" {
			return fmt.Errorf("app must not be blank")
		}

		if uploadVersion == "" {
			return fmt.Errorf("version must not be blank")
		}

		f, err := os.Open(bundleFile)
		if err != nil {
			return fmt.Errorf("could not open bundle: %w", err)
		}
		defer f.Close()

		ab, err := bundle.LoadBundle(f)
		if err != nil {
			return fmt.Errorf("could not load bundle: %w", err)
		}

		buf := &bytes.Buffer{}
		err = ab.WriteBundle(buf)
		if err != nil {
			return fmt.Errorf("could not re-create bundle: %w", err)
		}

		uploadBundle := &TidbytBundleUpload{
			AppID:   uploadAppID,
			Version: uploadVersion,
			Bundle:  base64.StdEncoding.EncodeToString(buf.Bytes()),
		}

		b, err := json.Marshal(uploadBundle)
		if err != nil {
			return fmt.Errorf("could not marshal request: %w", err)
		}

		requestURL := fmt.Sprintf("%s/v0/apps/%s/upload", uploadURL, uploadAppID)
		req, err := http.NewRequest(http.MethodPost, requestURL, bytes.NewReader(b))
		if err != nil {
			return fmt.Errorf("could not create http request: %w", err)
		}

		req.Header.Set("Content-Type", "application/json")
		req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiToken))

		client := http.Client{
			Timeout: 30 * time.Second,
		}

		resp, err := client.Do(req)
		if err != nil {
			return fmt.Errorf("could not make HTTP request to %s: %w", requestURL, err)
		}
		defer resp.Body.Close()

		if resp.StatusCode != 200 {
			body, _ := io.ReadAll(resp.Body)
			return fmt.Errorf("request returned status %d with message: %s", resp.StatusCode, body)
		}

		return nil
	},
}

Functions

This section is empty.

Types

type TidbytApp

type TidbytApp struct {
	ID             string `json:"id"`
	Name           string `json:"name,omitempty"`
	Version        string `json:"version,omitempty"`
	Private        bool   `json:"private,omitempty"`
	OrganizationID string `json:"organizationID,omitempty"`
}

type TidbytAppDeploy

type TidbytAppDeploy struct {
	AppID   string `json:"appID"`
	Version string `json:"version"`
}

type TidbytBundleUpload

type TidbytBundleUpload struct {
	AppID   string `json:"appID"`
	Version string `json:"version"`
	Bundle  string `json:"bundle"`
}

type TidbytCreateAppReply

type TidbytCreateAppReply struct {
	AppID string `json:"appID"`
}

type TidbytCreateAppRequest

type TidbytCreateAppRequest struct {
	OrganizationID string `json:"organizationID"`
	Private        bool   `json:"private"`
}

Jump to

Keyboard shortcuts

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