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
2 changes: 1 addition & 1 deletion cli/cmd/download_package.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (c *DownloadPackageCmd) RunE(_ *cobra.Command, args []string) error {
fmt.Printf("Downloading package %s\n", c.Opts.Version)

p := portal.NewPortalClient()
build, err := p.GetCodesphereBuildByVersion(c.Opts.Version)
build, err := p.GetBuild(portal.CodesphereProduct, c.Opts.Version)
if err != nil {
return fmt.Errorf("failed to get codesphere package: %w", err)
}
Expand Down
2 changes: 0 additions & 2 deletions cli/cmd/install-ceph.go → cli/cmd/install_ceph.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>

*/
package cmd

Expand Down Expand Up @@ -51,4 +50,3 @@ to quickly create a Cobra application.`,
// Add child commands here
// AddCephChildCmd(ceph.cmd)
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/*
Copyright © 2025 NAME HERE <EMAIL ADDRESS>

*/
package cmd

Expand Down Expand Up @@ -51,4 +50,3 @@ to quickly create a Cobra application.`,
// Add child commands here
// AddCodesphereChildCmd(codesphere.cmd)
}

61 changes: 61 additions & 0 deletions cli/cmd/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package cmd

import (
"fmt"
"time"

"github.com/codesphere-cloud/cs-go/pkg/io"
"github.com/codesphere-cloud/oms/internal/portal"
"github.com/spf13/cobra"
)

type RegisterCmd struct {
cmd *cobra.Command
Opts RegisterOpts
}

type RegisterOpts struct {
GlobalOptions
Owner string
Organization string
Role string
ExpiresAt string
}

func (c *RegisterCmd) RunE(_ *cobra.Command, args []string) error {
p := portal.NewPortalClient()
return c.Register(p)
}

func (c *RegisterCmd) Register(p portal.Portal) error {
expiresAt, err := time.Parse(time.RFC3339, c.Opts.ExpiresAt)
if err != nil {
return fmt.Errorf("failed to parse expiration date: %w", err)
}

err = p.RegisterAPIKey(c.Opts.Owner, c.Opts.Organization, c.Opts.Role, expiresAt)
if err != nil {
return fmt.Errorf("failed to register API key: %w", err)
}

return nil
}

func AddRegisterCmd(list *cobra.Command, opts GlobalOptions) {
c := RegisterCmd{
cmd: &cobra.Command{
Use: "register",
Short: "Register a new API key",
Long: io.Long(`Register a new API key for accessing the OMS portal.`),
},
Opts: RegisterOpts{GlobalOptions: opts},
}
c.cmd.Flags().StringVarP(&c.Opts.Owner, "owner", "o", "", "Owner of the new API key")
c.cmd.Flags().StringVarP(&c.Opts.Organization, "organization", "g", "", "Organization of the new API key")
c.cmd.Flags().StringVarP(&c.Opts.Role, "role", "r", "Ext", "Role of the new API key. Available roles: Admin, Dev, Ext")
c.cmd.Flags().StringVarP(&c.Opts.ExpiresAt, "expires", "e", "", "Expiration date of the new API key. Default is 1 year from now. Format: RFC3339 (e.g., 2024-12-31T23:59:59Z)")

c.cmd.RunE = c.RunE

list.AddCommand(c.cmd)
}
82 changes: 82 additions & 0 deletions cli/cmd/register_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package cmd_test

import (
"fmt"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/cobra"

"github.com/codesphere-cloud/oms/cli/cmd"
"github.com/codesphere-cloud/oms/internal/portal"
)

var _ = Describe("RegisterCmd", func() {
var (
mockPortal *portal.MockPortal
c cmd.RegisterCmd
expiresAt string
owner string
organization string
role string
)

BeforeEach(func() {
mockPortal = portal.NewMockPortal(GinkgoT())
expiresAt = "2025-05-01T15:04:05Z"
owner = "test-owner"
organization = "test-org"
role = "admin"
c = cmd.RegisterCmd{
Opts: cmd.RegisterOpts{
Owner: owner,
Organization: organization,
Role: role,
ExpiresAt: expiresAt,
},
}
})

Context("when expiration date is valid", func() {
It("registers the API key successfully", func() {
parsedTime, _ := time.Parse(time.RFC3339, expiresAt)
mockPortal.EXPECT().RegisterAPIKey(owner, organization, role, parsedTime).Return(nil)
err := c.Register(mockPortal)
Expect(err).To(BeNil())
})

It("returns error if Register fails", func() {
parsedTime, _ := time.Parse(time.RFC3339, expiresAt)
mockPortal.EXPECT().RegisterAPIKey(owner, organization, role, parsedTime).Return(fmt.Errorf("some error"))
err := c.Register(mockPortal)
Expect(err).To(MatchError(ContainSubstring("failed to register API key")))
})
})

Context("when expiration date is invalid", func() {
BeforeEach(func() {
c.Opts.ExpiresAt = "invalid-date"
})
It("returns error for invalid expiration date", func() {
err := c.Register(mockPortal)
Expect(err).To(MatchError(ContainSubstring("failed to parse expiration date")))
})
})
})

var _ = Describe("AddRegisterCmd", func() {
It("adds the register command to the parent", func() {
parent := &cobra.Command{}
opts := cmd.GlobalOptions{}
cmd.AddRegisterCmd(parent, opts)
found := false
for _, c := range parent.Commands() {
if c.Use == "register" {
found = true
break
}
}
Expect(found).To(BeTrue())
})
})
49 changes: 49 additions & 0 deletions cli/cmd/revoke.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cmd

import (
"fmt"

"github.com/codesphere-cloud/cs-go/pkg/io"
"github.com/codesphere-cloud/oms/internal/portal"
"github.com/spf13/cobra"
)

type RevokeCmd struct {
cmd *cobra.Command
Opts RevokeOpts
}

type RevokeOpts struct {
GlobalOptions
Key string
}

func (c *RevokeCmd) RunE(_ *cobra.Command, args []string) error {
p := portal.NewPortalClient()
return c.Revoke(p)
}

func (c *RevokeCmd) Revoke(p portal.Portal) error {
err := p.RevokeAPIKey(c.Opts.Key)
if err != nil {
return fmt.Errorf("failed to revoke API key: %w", err)
}

return nil
}

func AddRevokeCmd(list *cobra.Command, opts GlobalOptions) {
c := RevokeCmd{
cmd: &cobra.Command{
Use: "revoke",
Short: "Revoke an API key",
Long: io.Long(`Revoke an OMS portal API key.`),
},
Opts: RevokeOpts{GlobalOptions: opts},
}
c.cmd.Flags().StringVarP(&c.Opts.Key, "key", "k", "", "API key to revoke")

c.cmd.RunE = c.RunE

list.AddCommand(c.cmd)
}
62 changes: 62 additions & 0 deletions cli/cmd/revoke_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package cmd_test

import (
"fmt"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"github.com/spf13/cobra"

"github.com/codesphere-cloud/oms/cli/cmd"
"github.com/codesphere-cloud/oms/internal/portal"
)

var _ = Describe("RevokeCmd", func() {
var (
mockPortal *portal.MockPortal
c cmd.RevokeCmd
key string
)

BeforeEach(func() {
mockPortal = portal.NewMockPortal(GinkgoT())
key = "test-key"
c = cmd.RevokeCmd{
Opts: cmd.RevokeOpts{
Key: key,
},
}
})

Context("when revoking API key succeeds", func() {
It("returns nil error", func() {
mockPortal.EXPECT().RevokeAPIKey(key).Return(nil)
err := c.Revoke(mockPortal)
Expect(err).To(BeNil())
})
})

Context("when revoking API key fails", func() {
It("returns error", func() {
mockPortal.EXPECT().RevokeAPIKey(key).Return(fmt.Errorf("some error"))
err := c.Revoke(mockPortal)
Expect(err).To(MatchError(ContainSubstring("failed to revoke API key")))
})
})
})

var _ = Describe("AddRevokeCmd", func() {
It("adds the revoke command to the parent", func() {
parent := &cobra.Command{}
opts := cmd.GlobalOptions{}
cmd.AddRevokeCmd(parent, opts)
found := false
for _, c := range parent.Commands() {
if c.Use == "revoke" {
found = true
break
}
}
Expect(found).To(BeTrue())
})
})
5 changes: 3 additions & 2 deletions cli/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package cmd

import (
"fmt"
"golang.org/x/sync/errgroup"
"io"
"strings"

"golang.org/x/sync/errgroup"

"github.com/blang/semver"
"github.com/inconshreveable/go-update"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -45,7 +46,7 @@ func AddUpdateCmd(rootCmd *cobra.Command) {
func (c *UpdateCmd) SelfUpdate(p portal.Portal) error {
currentVersion := semver.MustParse(c.Version.Version())

latest, err := p.GetLatestBuild(portal.OmsProduct, "")
latest, err := p.GetBuild(portal.OmsProduct, "")
if err != nil {
return fmt.Errorf("failed to query OMS Portal for latest version: %w", err)
}
Expand Down
6 changes: 3 additions & 3 deletions cli/cmd/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ var _ = Describe("Update", func() {
mockVersion.EXPECT().Arch().Return("fakearch")
mockVersion.EXPECT().Version().Return("0.0.0")
mockVersion.EXPECT().Os().Return("fakeos")
mockPortal.EXPECT().GetLatestBuild(portal.OmsProduct, "").Return(latestBuild, nil)
mockPortal.EXPECT().GetBuild(portal.OmsProduct, "").Return(latestBuild, nil)
mockPortal.EXPECT().DownloadBuildArtifact(portal.OmsProduct, buildToDownload, mock.Anything).RunAndReturn(
func(product portal.Product, build portal.Build, file io.Writer) error {
embeddedFile, err := testdata.Open("testdata/testcli.tar.gz")
Expand All @@ -88,9 +88,9 @@ var _ = Describe("Update", func() {
Expect(err).NotTo(HaveOccurred())
})

It("Detects when current verison is latest version", func() {
It("Detects when current version is latest version", func() {
mockVersion.EXPECT().Version().Return(latestBuild.Version)
mockPortal.EXPECT().GetLatestBuild(portal.OmsProduct, "").Return(latestBuild, nil)
mockPortal.EXPECT().GetBuild(portal.OmsProduct, "").Return(latestBuild, nil)
err := c.SelfUpdate(mockPortal)
Expect(err).NotTo(HaveOccurred())
})
Expand Down
File renamed without changes.
File renamed without changes.
Loading