Skip to content

Commit

Permalink
Merge pull request #1161 from romayalon/romy-cosi-access-cli
Browse files Browse the repository at this point in the history
COSI | CLI | Bucket Access Class & Bucket Access implementation
  • Loading branch information
romayalon authored Jul 20, 2023
2 parents 18f09ee + c52a2a5 commit 697e51a
Show file tree
Hide file tree
Showing 8 changed files with 719 additions and 12 deletions.
19 changes: 18 additions & 1 deletion doc/cosi-provisioner.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,9 @@ parameters:
```
The equivalent noobaa cli command -
```shell
noobaa cosi bucketclass create placement-bucketclass my-cosi-bucket-class --backingstores noobaa-default-backing-store
```

 
Example of namespace bucketclass:
Expand All @@ -122,7 +123,10 @@ parameters:
```
The equivalent noobaa cli command -
```shell
noobaa cosi bucketclass create namespace-bucketclass single my-cosi-ns-bucket-class --resource nsr-name
```


 
Example of namespace bucketclass with a replication policy:
Expand All @@ -144,6 +148,8 @@ The equivalent noobaa cli command -
```shell
noobaa cosi bucketclass create placement-bucketclass my-cosi-ns-bucket-class --backingstores noobaa-default-backing-store
--replication-policy=/path/to/json-file.json
```


## COSI Bucket Claim

Expand All @@ -168,7 +174,10 @@ spec:
```
The equivalent noobaa cli command -
```shell
noobaa cosi bucketclaim create my-cosi-bucket-claim --bucketclass my-cosi-bucket-class
```


## COSI BucketAccessClass

Expand All @@ -185,6 +194,10 @@ driverName: noobaa.objectstorage.k8s.io
authenticationType: KEY
```
The equivalent noobaa cli command -
```shell
noobaa cosi accessclass create my-cosi-bucket-access-class
```
# COSI BucketAccess claim

An administrator of a noobaa deployment can create BucketAccess claim that refers to a BucketAccessClass in order to get credentials that will provide access to a COSI bucket claim. NooBaa will generate an account and will return credentials as the bucket access claim response, then a Secret (named by credentialsSecretName property) containing the bucket info will be created. The properties bucketClaimName, bucketAccessClassName and credentialsSecretName are all required values.
Expand All @@ -204,6 +217,10 @@ spec:
credentialsSecretName: my-cosi-bucket-creds
```
The equivalent noobaa cli command -
```shell
noobaa cosi accessclaim create my-cosi-bucket-access --bucket-claim=my-cosi-bucket-claim --bucket-access-class=my-cosi-bucket-access-class --creds-secret-name=my-cosi-bucket-creds
```
# Using the COSI bucket claim

Once the COSI bucket claim is provisioned by the operator, a bucket will be created in NooBaa, a Secret bucket info will be created. For the example above, the Secret will be named `my-cosi-bucket-creds`.
Expand Down
24 changes: 23 additions & 1 deletion pkg/apis/noobaa/v1alpha1/cosi_types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1alpha1

import (
cosiapis "sigs.k8s.io/container-object-storage-interface-api/apis"
cosiapi "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage"
cosiv1 "sigs.k8s.io/container-object-storage-interface-api/apis/objectstorage/v1alpha1"
)
Expand Down Expand Up @@ -41,5 +42,26 @@ const COSIS3Protocol = cosiv1.ProtocolS3
// COSIDeletionPolicyRetain is a constant represents a retain deletion policy
const COSIDeletionPolicyRetain = cosiv1.DeletionPolicyRetain

// COSIDeletionPolicyDelete is a constant represents a delete deletion policy
// COSIDeletionPolicyDelete is a constant represents a delete deletion policy
const COSIDeletionPolicyDelete = cosiv1.DeletionPolicyDelete

// COSIBucketAccessClass is the API type for submitting access classes
type COSIBucketAccessClass = cosiv1.BucketAccessClass

// COSIBucketAccessClassList is a list of COSIAccessClass
type COSIBucketAccessClassList = cosiv1.BucketAccessClassList

// COSIAuthenticationType is the API type represents bucket access class authentication type
type COSIAuthenticationType = cosiv1.AuthenticationType

// COSIKEYAuthenticationType is a constant represents a KEY authentication type (secret tokens based authentication)
const COSIKEYAuthenticationType = cosiv1.AuthenticationTypeKey

// COSIBucketAccessClaim is the API type for submitting bucket access claims
type COSIBucketAccessClaim = cosiv1.BucketAccess

// COSIBucketAccessClaimList is a list of COSIBucketAccessClaim
type COSIBucketAccessClaimList = cosiv1.BucketAccessList

// COSIBucketInfo is the API type represents bucket info
type COSIBucketInfo = cosiapis.BucketInfo
4 changes: 3 additions & 1 deletion pkg/cosi/cosi.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ func Cmd() *cobra.Command {
Short: "Manage cosi resources",
}
cmd.AddCommand(
CmdCOSIBucketClaim(),
CmdCOSIBucketClass(),
CmdCOSIBucketClaim(),
CmdCOSIBucketAccessClass(),
CmdCOSIBucketAccessClaim(),
)
return cmd
}
166 changes: 166 additions & 0 deletions pkg/cosi/cosi_access_class.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package cosi

import (
"fmt"
"time"

"github.com/noobaa/noobaa-operator/v5/pkg/bundle"
"github.com/noobaa/noobaa-operator/v5/pkg/options"
"github.com/noobaa/noobaa-operator/v5/pkg/util"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

nbv1 "github.com/noobaa/noobaa-operator/v5/pkg/apis/noobaa/v1alpha1"
)

// CmdCOSIBucketAccessClass returns a CLI command
func CmdCOSIBucketAccessClass() *cobra.Command {
cmd := &cobra.Command{
Use: "accessclass",
Short: "Manage cosi access class",
}
cmd.AddCommand(
CmdCreateAccessClass(),
CmdDeleteAccessClass(),
CmdStatusAccessClass(),
CmdListAccessClass(),
)
return cmd
}

// CmdCreateAccessClass returns a CLI command
func CmdCreateAccessClass() *cobra.Command {
cmd := &cobra.Command{
Use: "create <access-class-name>",
Short: "Create a COSI access class",
Run: RunCreateAccessClass,
}
// AuthenticationType - valid types are KEY / IAM - currently the only supported type is KEY
// Parameters - currently no extra parameters are supported
return cmd
}

// CmdDeleteAccessClass returns a CLI command
func CmdDeleteAccessClass() *cobra.Command {
cmd := &cobra.Command{
Use: "delete <access-class-name>",
Short: "Delete a COSI access class",
Run: RunDeleteAccessClass,
}

return cmd
}

// CmdStatusAccessClass returns a CLI command
func CmdStatusAccessClass() *cobra.Command {
cmd := &cobra.Command{
Use: "status <access-class-name>",
Short: "Status of a COSI access class",
Run: RunStatusAccessClass,
}
return cmd
}

// CmdListAccessClass returns a CLI command
func CmdListAccessClass() *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List COSI access classes",
Run: RunListAccessClass,
Args: cobra.NoArgs,
}
return cmd
}

// RunCreateAccessClass runs a CLI command
func RunCreateAccessClass(cmd *cobra.Command, args []string) {
log := util.Logger()

if len(args) != 1 || args[0] == "" {
log.Fatalf(`Missing expected arguments: <access-class-name> %s`, cmd.UsageString())
}
name := args[0]

cosiAccessClass := util.KubeObject(bundle.File_deploy_cosi_bucket_access_class_yaml).(*nbv1.COSIBucketAccessClass)
cosiAccessClass.Name = name
cosiAccessClass.DriverName = options.COSIDriverName()
cosiAccessClass.AuthenticationType = nbv1.COSIKEYAuthenticationType

if !util.KubeCreateFailExisting(cosiAccessClass) {
log.Fatalf(`❌ Could not create COSI access class %q (conflict)`, cosiAccessClass.Name)
}

log.Printf("")
log.Printf("")
log.Printf("")
RunStatusAccessClass(cmd, args)
}

// RunDeleteAccessClass runs a CLI command
func RunDeleteAccessClass(cmd *cobra.Command, args []string) {
log := util.Logger()

if len(args) != 1 || args[0] == "" {
log.Fatalf(`Missing expected arguments: <access-class-name> %s`, cmd.UsageString())
}

cosiAccessClass := util.KubeObject(bundle.File_deploy_cosi_bucket_access_class_yaml).(*nbv1.COSIBucketAccessClass)
cosiAccessClass.Name = args[0]

if !util.KubeDelete(cosiAccessClass) {
log.Fatalf(`❌ Could not delete COSI access class %q `, cosiAccessClass.Name)
}
}

// RunStatusAccessClass runs a CLI command
func RunStatusAccessClass(cmd *cobra.Command, args []string) {
log := util.Logger()

if len(args) != 1 || args[0] == "" {
log.Fatalf(`Missing expected arguments: <access-class-name> %s`, cmd.UsageString())
}

cosiAccessClass := util.KubeObject(bundle.File_deploy_cosi_bucket_access_class_yaml).(*nbv1.COSIBucketAccessClass)
cosiAccessClass.Name = args[0]

if !util.KubeCheck(cosiAccessClass) {
log.Fatalf(`❌ Could not find COSI access class %q`, cosiAccessClass.Name)
}

fmt.Println()
fmt.Println("# AccessClass spec:")
fmt.Printf("Name:\n %s\n", cosiAccessClass.Name)
fmt.Printf("Driver Name:\n %s\n", cosiAccessClass.DriverName)
fmt.Printf("Authentication Type:\n %+v", cosiAccessClass.AuthenticationType)
fmt.Println()
}

// RunListAccessClass runs a CLI command
func RunListAccessClass(cmd *cobra.Command, args []string) {
list := &nbv1.COSIBucketAccessClassList{
TypeMeta: metav1.TypeMeta{Kind: "AccessClass"},
}
if !util.KubeList(list) {
return
}
if len(list.Items) == 0 {
fmt.Printf("No COSI access classes found.\n")
return
}
table := (&util.PrintTable{}).AddRow(
"NAME",
"DRIVER-NAME",
"AUTHENTICATION-TYPE",
"AGE",
)
for i := range list.Items {
cosiAccessClass := &list.Items[i]
table.AddRow(
cosiAccessClass.Name,
cosiAccessClass.DriverName,
string(cosiAccessClass.AuthenticationType),
util.HumanizeDuration(time.Since(cosiAccessClass.CreationTimestamp.Time).Round(time.Second)),
)
}
fmt.Print(table.String())
}
Loading

0 comments on commit 697e51a

Please sign in to comment.