package cli import ( "context" "fmt" "time" v1 "github.com/juanfont/headscale/gen/go/headscale/v1" "github.com/pterm/pterm" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) func init() { rootCmd.AddCommand(namespaceCmd) namespaceCmd.AddCommand(createNamespaceCmd) namespaceCmd.AddCommand(listNamespacesCmd) namespaceCmd.AddCommand(destroyNamespaceCmd) namespaceCmd.AddCommand(renameNamespaceCmd) } var namespaceCmd = &cobra.Command{ Use: "namespaces", Short: "Manage the namespaces of Headscale", } var createNamespaceCmd = &cobra.Command{ Use: "create NAME", Short: "Creates a new namespace", Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("Missing parameters") } return nil }, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") namespaceName := args[0] ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() client, conn := getHeadscaleGRPCClient(ctx) defer conn.Close() log.Trace().Interface("client", client).Msg("Obtained gRPC client") request := &v1.CreateNamespaceRequest{Name: namespaceName} log.Trace().Interface("request", request).Msg("Sending CreateNamespace request") response, err := client.CreateNamespace(ctx, request) if err != nil { ErrorOutput(err, fmt.Sprintf("Cannot create namespace: %s", err), output) return } SuccessOutput(response.Namespace, "Namespace created", output) }, } var destroyNamespaceCmd = &cobra.Command{ Use: "destroy NAME", Short: "Destroys a namespace", Args: func(cmd *cobra.Command, args []string) error { if len(args) < 1 { return fmt.Errorf("Missing parameters") } return nil }, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") namespaceName := args[0] ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() client, conn := getHeadscaleGRPCClient(ctx) defer conn.Close() request := &v1.DeleteNamespaceRequest{Name: namespaceName} response, err := client.DeleteNamespace(ctx, request) if err != nil { ErrorOutput(err, fmt.Sprintf("Cannot destroy namespace: %s", err), output) return } SuccessOutput(response, "Namespace destroyed", output) }, } var listNamespacesCmd = &cobra.Command{ Use: "list", Short: "List all the namespaces", Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() client, conn := getHeadscaleGRPCClient(ctx) defer conn.Close() request := &v1.ListNamespacesRequest{} response, err := client.ListNamespaces(ctx, request) if err != nil { ErrorOutput(err, fmt.Sprintf("Cannot get namespaces: %s", err), output) return } if output != "" { SuccessOutput(response.Namespaces, "", output) return } d := pterm.TableData{{"ID", "Name", "Created"}} for _, namespace := range response.GetNamespaces() { d = append( d, []string{ namespace.GetId(), namespace.GetName(), namespace.GetCreatedAt().AsTime().Format("2006-01-02 15:04:05"), }, ) } err = pterm.DefaultTable.WithHasHeader().WithData(d).Render() if err != nil { ErrorOutput(err, fmt.Sprintf("Failed to render pterm table: %s", err), output) return } }, } var renameNamespaceCmd = &cobra.Command{ Use: "rename OLD_NAME NEW_NAME", Short: "Renames a namespace", Args: func(cmd *cobra.Command, args []string) error { if len(args) < 2 { return fmt.Errorf("Missing parameters") } return nil }, Run: func(cmd *cobra.Command, args []string) { output, _ := cmd.Flags().GetString("output") ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) defer cancel() client, conn := getHeadscaleGRPCClient(ctx) defer conn.Close() request := &v1.RenameNamespaceRequest{ OldName: args[0], NewName: args[1], } response, err := client.RenameNamespace(ctx, request) if err != nil { ErrorOutput(err, fmt.Sprintf("Cannot rename namespace: %s", err), output) return } SuccessOutput(response.Namespace, "Namespace renamed", output) }, }