Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion app/cli/cmd/casbackend.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func newCASBackendCmd() *cobra.Command {
Short: "Operations on Artifact CAS backends",
}

cmd.AddCommand(newCASBackendListCmd(), newCASBackendAddCmd())
cmd.AddCommand(newCASBackendListCmd(), newCASBackendAddCmd(), newCASBackendUpdateCmd())
return cmd
}

Expand All @@ -41,3 +41,16 @@ func newCASBackendAddCmd() *cobra.Command {
cmd.AddCommand(newCASBackendAddOCICmd())
return cmd
}

func newCASBackendUpdateCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "Update a CAS backend description, credentials or default status",
}

cmd.PersistentFlags().Bool("default", false, "set the backend as default in your organization")
cmd.PersistentFlags().String("description", "", "descriptive information for this registration")

cmd.AddCommand(newCASBackendUpdateOCICmd())
return cmd
}
37 changes: 21 additions & 16 deletions app/cli/cmd/casbackend_add_oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"fmt"

"github.com/chainloop-dev/chainloop/app/cli/internal/action"
"github.com/go-kratos/kratos/v2/log"
"github.com/spf13/cobra"
)

Expand All @@ -37,18 +38,25 @@ func newCASBackendAddOCICmd() *cobra.Command {
cobra.CheckErr(err)

if isDefault {
if confirmed, err := confirmDefaultCASBackendOverride(actionOpts); err != nil {
if confirmed, err := confirmDefaultCASBackendOverride(actionOpts, ""); err != nil {
return err
} else if !confirmed {
fmt.Println("Aborting...")
log.Info("Aborting...")
return nil
}
}

opts := &action.NewCASBackendOCIAddOpts{
Repo: repo, Username: username, Password: password, Default: isDefault, Description: description,
opts := &action.NewCASBackendAddOpts{
Location: repo, Description: description,
Provider: "OCI",
Credentials: map[string]any{
"username": username,
"password": password,
},
Default: isDefault,
}

res, err := action.NewCASBackendAddOCI(actionOpts).Run(opts)
res, err := action.NewCASBackendAdd(actionOpts).Run(opts)
if err != nil {
return err
} else if res == nil {
Expand All @@ -74,24 +82,25 @@ func newCASBackendAddOCICmd() *cobra.Command {
}

// confirmDefaultCASBackendOverride asks the user to confirm the override of the default CAS backend
// in the event that there is one already set.
func confirmDefaultCASBackendOverride(actionOpts *action.ActionsOpts) (bool, error) {
// in the event that there is one already set and its not the same as the one we are setting
func confirmDefaultCASBackendOverride(actionOpts *action.ActionsOpts, id string) (bool, error) {
// get existing backends
backends, err := action.NewCASBackendList(actionOpts).Run()
if err != nil {
return false, fmt.Errorf("failed to list existing CAS backends: %w", err)
}

var hasDefault bool
// Find the default
var defaultB *action.CASBackendItem
for _, b := range backends {
if b.Default {
hasDefault = true
defaultB = b
break
}
}

// If there is none, we are done
if !hasDefault {
// If there is none or there is but it's the same as the one we are setting, we are ok
if defaultB == nil || (id != "" && id == defaultB.ID) {
return true, nil
}

Expand All @@ -101,9 +110,5 @@ func confirmDefaultCASBackendOverride(actionOpts *action.ActionsOpts) (bool, err
fmt.Scanln(&gotChallenge)

// If the user does not confirm, we are done
if gotChallenge != "y" && gotChallenge != "Y" {
return false, nil
}

return true, nil
return gotChallenge == "y" || gotChallenge == "Y", nil
}
116 changes: 116 additions & 0 deletions app/cli/cmd/casbackend_update_oci.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
//
// Copyright 2023 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"fmt"

"github.com/chainloop-dev/chainloop/app/cli/internal/action"
"github.com/go-kratos/kratos/v2/log"
"github.com/spf13/cobra"
)

func newCASBackendUpdateOCICmd() *cobra.Command {
var backendID, username, password string
cmd := &cobra.Command{
Use: "oci",
Short: "Update a OCI CAS Backend description, credentials or default status",
RunE: func(cmd *cobra.Command, args []string) error {
// If we are setting the default, we list existing CAS backends
// and ask the user to confirm the rewrite
isDefault, err := cmd.Flags().GetBool("default")
cobra.CheckErr(err)

description, err := cmd.Flags().GetString("description")
cobra.CheckErr(err)

// If we are overriding the default we ask for confirmation
if isDefault {
if confirmed, err := confirmDefaultCASBackendOverride(actionOpts, backendID); err != nil {
return err
} else if !confirmed {
log.Info("Aborting...")
return nil
}
} else { // If we are removing the default we ask for confirmation too
if confirmed, err := confirmDefaultCASBackendRemoval(actionOpts, backendID); err != nil {
return err
} else if !confirmed {
log.Info("Aborting...")
return nil
}
}

opts := &action.NewCASBackendUpdateOpts{
ID: backendID,
Description: description,
Credentials: map[string]any{
"username": username,
"password": password,
},
Default: isDefault,
}

if username == "" && password == "" {
opts.Credentials = nil
}

res, err := action.NewCASBackendUpdate(actionOpts).Run(opts)
if err != nil {
return err
} else if res == nil {
return nil
}

return encodeOutput([]*action.CASBackendItem{res}, casBackendListTableOutput)
},
}

cmd.Flags().StringVar(&backendID, "id", "", "CAS Backend ID")
err := cmd.MarkFlagRequired("id")
cobra.CheckErr(err)

cmd.Flags().StringVarP(&username, "username", "u", "", "registry username")

cmd.Flags().StringVarP(&password, "password", "p", "", "registry password")
return cmd
}

// If we are removing the default we confirm too
func confirmDefaultCASBackendRemoval(actionOpts *action.ActionsOpts, id string) (bool, error) {
// get existing backends
backends, err := action.NewCASBackendList(actionOpts).Run()
if err != nil {
return false, fmt.Errorf("failed to list existing CAS backends: %w", err)
}

for _, b := range backends {
// We are removing ourselves as the default, ask the user to confirm
if b.Default && b.ID == id {
// Ask the user to confirm the override
fmt.Println("This is the default CAS backend and your are setting default=false.\nPlease confirm to continue y/N: ")
var gotChallenge string
fmt.Scanln(&gotChallenge)

// If the user does not confirm, we are done
if gotChallenge != "y" && gotChallenge != "Y" {
return false, nil
}
}
}

return true, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,33 @@ import (
"google.golang.org/protobuf/types/known/structpb"
)

type CASBackendAddOCI struct {
type CASBackendAdd struct {
cfg *ActionsOpts
}

type NewCASBackendOCIAddOpts struct {
Repo, Username, Password string
Description string
Default bool
type NewCASBackendAddOpts struct {
Location string
Provider string
Description string
Default bool
Credentials map[string]any
}

func NewCASBackendAddOCI(cfg *ActionsOpts) *CASBackendAddOCI {
return &CASBackendAddOCI{cfg}
func NewCASBackendAdd(cfg *ActionsOpts) *CASBackendAdd {
return &CASBackendAdd{cfg}
}

func (action *CASBackendAddOCI) Run(opts *NewCASBackendOCIAddOpts) (*CASBackendItem, error) {
func (action *CASBackendAdd) Run(opts *NewCASBackendAddOpts) (*CASBackendItem, error) {
// Custom configuration for OCI
credentials, err := structpb.NewStruct(map[string]any{
"username": opts.Username,
"password": opts.Password,
})
credentials, err := structpb.NewStruct(opts.Credentials)
if err != nil {
return nil, fmt.Errorf("failed to parse arguments: %w", err)
}

client := pb.NewCASBackendServiceClient(action.cfg.CPConnection)
resp, err := client.Create(context.Background(), &pb.CASBackendServiceCreateRequest{
Location: opts.Repo,
Provider: "OCI",
Location: opts.Location,
Provider: opts.Provider,
Description: opts.Description,
Default: opts.Default,
Credentials: credentials,
Expand Down
64 changes: 64 additions & 0 deletions app/cli/internal/action/casbackend_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
//
// Copyright 2023 The Chainloop Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package action

import (
"context"
"fmt"

pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1"
"google.golang.org/protobuf/types/known/structpb"
)

type CASBackendUpdate struct {
cfg *ActionsOpts
}

type NewCASBackendUpdateOpts struct {
ID string
Description string
Default bool
Credentials map[string]any
}

func NewCASBackendUpdate(cfg *ActionsOpts) *CASBackendUpdate {
return &CASBackendUpdate{cfg}
}

func (action *CASBackendUpdate) Run(opts *NewCASBackendUpdateOpts) (*CASBackendItem, error) {
var credentials *structpb.Struct
var err error

if opts.Credentials != nil {
credentials, err = structpb.NewStruct(opts.Credentials)
if err != nil {
return nil, fmt.Errorf("failed to parse arguments: %w", err)
}
}

client := pb.NewCASBackendServiceClient(action.cfg.CPConnection)
resp, err := client.Update(context.Background(), &pb.CASBackendServiceUpdateRequest{
Id: opts.ID,
Description: opts.Description,
Default: opts.Default,
Credentials: credentials,
})
if err != nil {
return nil, err
}

return pbCASBackendItemToAction(resp.Result), nil
}
Loading