github.com/pachyderm/pachyderm@v1.13.4/src/server/enterprise/cmds/cmds.go (about)

     1  package cmds
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/pachyderm/pachyderm/src/client"
     8  	"github.com/pachyderm/pachyderm/src/client/enterprise"
     9  	"github.com/pachyderm/pachyderm/src/client/pkg/errors"
    10  	"github.com/pachyderm/pachyderm/src/server/pkg/cmdutil"
    11  
    12  	"github.com/gogo/protobuf/types"
    13  	"github.com/spf13/cobra"
    14  )
    15  
    16  // Unfortunately, Go's pre-defined format strings for parsing RFC-3339-compliant
    17  // timestamps aren't exhaustive. This method attempts to parse a larger set of
    18  // of ISO-8601-compatible timestamps (which are themselves a subset of RFC-3339
    19  // timestamps)
    20  func parseISO8601(s string) (time.Time, error) {
    21  	t, err := time.Parse(time.RFC3339, s)
    22  	if err == nil {
    23  		return t, nil
    24  	}
    25  	t, err = time.Parse("2006-01-02T15:04:05Z0700", s)
    26  	if err == nil {
    27  		return t, nil
    28  	}
    29  	return time.Time{}, errors.Errorf("could not parse \"%s\" as any of %v", s, []string{time.RFC3339, "2006-01-02T15:04:05Z0700"})
    30  }
    31  
    32  // ActivateCmd returns a cobra.Command to activate the enterprise features of
    33  // Pachyderm within a Pachyderm cluster. All repos will go from
    34  // publicly-accessible to accessible only by the owner, who can subsequently add
    35  // users
    36  func ActivateCmd() *cobra.Command {
    37  	var expires string
    38  	activate := &cobra.Command{
    39  		Use: "{{alias}}",
    40  		Short: "Activate the enterprise features of Pachyderm with an activation " +
    41  			"code",
    42  		Long: "Activate the enterprise features of Pachyderm with an activation " +
    43  			"code",
    44  		Run: cmdutil.RunFixedArgs(0, func(args []string) error {
    45  			// request the enterprise key
    46  			key, err := cmdutil.ReadPassword("Enterprise key: ")
    47  			if err != nil {
    48  				return errors.Wrapf(err, "could not read enterprise key")
    49  			}
    50  
    51  			c, err := client.NewOnUserMachine("user")
    52  			if err != nil {
    53  				return errors.Wrapf(err, "could not connect")
    54  			}
    55  			defer c.Close()
    56  			req := &enterprise.ActivateRequest{}
    57  			req.ActivationCode = key
    58  			if expires != "" {
    59  				t, err := parseISO8601(expires)
    60  				if err != nil {
    61  					return errors.Wrapf(err, "could not parse the timestamp \"%s\"", expires)
    62  				}
    63  				req.Expires, err = types.TimestampProto(t)
    64  				if err != nil {
    65  					return errors.Wrapf(err, "error converting expiration time \"%s\"", t.String())
    66  				}
    67  			}
    68  			resp, err := c.Enterprise.Activate(c.Ctx(), req)
    69  			if err != nil {
    70  				return err
    71  			}
    72  			ts, err := types.TimestampFromProto(resp.Info.Expires)
    73  			if err != nil {
    74  				return errors.Wrapf(err, "activation request succeeded, but could not "+
    75  					"convert token expiration time to a timestamp", err)
    76  			}
    77  			fmt.Printf("Activation succeeded. Your Pachyderm Enterprise token "+
    78  				"expires %s\n", ts.String())
    79  			return nil
    80  		}),
    81  	}
    82  	activate.PersistentFlags().StringVar(&expires, "expires", "", "A timestamp "+
    83  		"indicating when the token provided above should expire (formatted as an "+
    84  		"RFC 3339/ISO 8601 datetime). This is only applied if it's earlier than "+
    85  		"the signed expiration time encoded in 'activation-code', and therefore "+
    86  		"is only useful for testing.")
    87  
    88  	return cmdutil.CreateAlias(activate, "enterprise activate")
    89  }
    90  
    91  // GetStateCmd returns a cobra.Command to activate the enterprise features of
    92  // Pachyderm within a Pachyderm cluster. All repos will go from
    93  // publicly-accessible to accessible only by the owner, who can subsequently add
    94  // users
    95  func GetStateCmd() *cobra.Command {
    96  	getState := &cobra.Command{
    97  		Short: "Check whether the Pachyderm cluster has enterprise features " +
    98  			"activated",
    99  		Long: "Check whether the Pachyderm cluster has enterprise features " +
   100  			"activated",
   101  		Run: cmdutil.Run(func(args []string) error {
   102  			c, err := client.NewOnUserMachine("user")
   103  			if err != nil {
   104  				return errors.Wrapf(err, "could not connect")
   105  			}
   106  			defer c.Close()
   107  			resp, err := c.Enterprise.GetState(c.Ctx(), &enterprise.GetStateRequest{})
   108  			if err != nil {
   109  				return err
   110  			}
   111  			if resp.State == enterprise.State_NONE {
   112  				fmt.Println("No Pachyderm Enterprise token was found")
   113  				return nil
   114  			}
   115  			ts, err := types.TimestampFromProto(resp.Info.Expires)
   116  			if err != nil {
   117  				return errors.Wrapf(err, "activation request succeeded, but could not "+
   118  					"convert token expiration time to a timestamp")
   119  			}
   120  			fmt.Printf("Pachyderm Enterprise token state: %s\nExpiration: %s\n",
   121  				resp.State.String(), ts.String())
   122  			return nil
   123  		}),
   124  	}
   125  	return cmdutil.CreateAlias(getState, "enterprise get-state")
   126  }
   127  
   128  // Cmds returns pachctl commands related to Pachyderm Enterprise
   129  func Cmds() []*cobra.Command {
   130  	var commands []*cobra.Command
   131  
   132  	enterprise := &cobra.Command{
   133  		Short: "Enterprise commands enable Pachyderm Enterprise features",
   134  		Long:  "Enterprise commands enable Pachyderm Enterprise features",
   135  	}
   136  	commands = append(commands, cmdutil.CreateAlias(enterprise, "enterprise"))
   137  
   138  	commands = append(commands, ActivateCmd())
   139  	commands = append(commands, GetStateCmd())
   140  
   141  	return commands
   142  }