Skip to content

Commit

Permalink
boxcli: devbox cache enable (#2157)
Browse files Browse the repository at this point in the history
Add a `devbox cache enable` subcommand that:

1. Opens a browser and performs the login flow is the user isn't logged
in.
2. Configures Nix to use the Jetify cache if it isn't already.

The login flow redirects to the new cloud.jetify.com/team/cache URL to
let the user know the cache is enabled.
  • Loading branch information
gcurtis committed Jun 20, 2024
1 parent de5bb79 commit ac28b01
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 6 deletions.
4 changes: 2 additions & 2 deletions internal/boxcli/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func loginCmd() *cobra.Command {
Short: "Login to devbox",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
c, err := identity.AuthClient()
c, err := identity.AuthClient(identity.AuthRedirectDefault)
if err != nil {
return err
}
Expand All @@ -62,7 +62,7 @@ func logoutCmd() *cobra.Command {
Short: "Logout from devbox",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
c, err := identity.AuthClient()
c, err := identity.AuthClient(identity.AuthRedirectDefault)
if err != nil {
return err
}
Expand Down
45 changes: 45 additions & 0 deletions internal/boxcli/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/spf13/cobra"
"go.jetpack.io/devbox/internal/devbox"
"go.jetpack.io/devbox/internal/devbox/devopt"
"go.jetpack.io/devbox/internal/devbox/providers/identity"
"go.jetpack.io/devbox/internal/devbox/providers/nixcache"
nixv1alpha1 "go.jetpack.io/pkg/api/gen/priv/nix/v1alpha1"
)
Expand Down Expand Up @@ -72,6 +73,7 @@ func cacheCmd() *cobra.Command {
cacheCommand.AddCommand(uploadCommand)
cacheCommand.AddCommand(cacheConfigureCmd())
cacheCommand.AddCommand(cacheCredentialsCmd())
cacheCommand.AddCommand(cacheEnableCmd())
cacheCommand.AddCommand(cacheInfoCmd())

return cacheCommand
Expand Down Expand Up @@ -143,6 +145,49 @@ func cacheCredentialsCmd() *cobra.Command {
return cmd
}

func cacheEnableCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "enable",
Short: "Enable the Devbox Nix cache for your account",
Long: heredoc.Doc(`
Sign up or log in to a Jetify Cloud account and configure Nix to use the
account's Nix cache.
For more about how Devbox configures Nix, see "devbox cache configure -h".
`),
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
auth, err := identity.AuthClient(identity.AuthRedirectCache)
if err != nil {
return err
}
sess, _ := auth.GetSessions()
needLogin := len(sess) == 0
if needLogin {
_, err = auth.LoginFlow()
if err != nil {
return err
}
}

needConfigure := !nixcache.IsConfigured(cmd.Context())
if needConfigure {
u, _ := user.Current()
err = nixcache.ConfigureReprompt(cmd.Context(), u.Username)
if err != nil {
return err
}
}

if !needConfigure && !needLogin {
fmt.Fprintln(cmd.OutOrStdout(), "The Devbox cache is already enabled for your account.")
}
return nil
},
}
return cmd
}

func cacheInfoCmd() *cobra.Command {
return &cobra.Command{
Use: "info",
Expand Down
20 changes: 16 additions & 4 deletions internal/devbox/providers/identity/identity.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"os"
"path"

"github.com/go-jose/go-jose/v4"
"github.com/go-jose/go-jose/v4/jwt"
Expand All @@ -16,6 +17,16 @@ import (
"golang.org/x/oauth2"
)

// Common redirect URLs for use with [AuthClient].
var (
// AuthRedirectDefault redirects to a generic success page.
AuthRedirectDefault = build.SuccessRedirect()

// AuthRedirectCache redirects to the "Cache" tab in the dashboard for
// the authenticated organization.
AuthRedirectCache = path.Join(build.DashboardHostname(), "team", "cache")
)

var scopes = []string{"openid", "offline_access", "email", "profile"}

var cachedAccessTokenFromAPIToken *session.Token
Expand All @@ -25,7 +36,7 @@ func GenSession(ctx context.Context) (*session.Token, error) {
return t, err
}

c, err := AuthClient()
c, err := AuthClient(AuthRedirectDefault)
if err != nil {
return nil, err
}
Expand All @@ -37,7 +48,7 @@ func Peek() (*session.Token, error) {
return cachedAccessTokenFromAPIToken, nil
}

c, err := AuthClient()
c, err := AuthClient(AuthRedirectDefault)
if err != nil {
return nil, err
}
Expand All @@ -53,12 +64,13 @@ func Peek() (*session.Token, error) {
return tokens[0].Peek(), nil
}

func AuthClient() (*auth.Client, error) {
// AuthClient returns a new client that redirects to a given URL upon success.
func AuthClient(redirect string) (*auth.Client, error) {
return auth.NewClient(
build.Issuer(),
build.ClientID(),
scopes,
build.SuccessRedirect(),
redirect,
build.Audience(),
)
}
Expand Down

0 comments on commit ac28b01

Please sign in to comment.