Skip to content
Draft
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
16 changes: 16 additions & 0 deletions cli/cmd/codesphere/codesphere_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) Codesphere Inc.
// SPDX-License-Identifier: Apache-2.0

package codesphere_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestCodesphere(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Codesphere Cmd Suite")
}
12 changes: 8 additions & 4 deletions cli/cmd/codesphere/smoketest_codesphere.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ type SmoketestCodesphereCmd struct {
Opts *teststeps.SmoketestCodesphereOpts
}

func (c *SmoketestCodesphereCmd) RunE(_ *cobra.Command, args []string) error {
// RunE runs the smoke test against the configured Codesphere installation.
func (c *SmoketestCodesphereCmd) RunE(cmd *cobra.Command, _ []string) error {
client, err := codesphere.NewClient(c.Opts.BaseURL, c.Opts.Token)
if err != nil {
return fmt.Errorf("failed to create Codesphere client: %w", err)
}
c.Opts.Client = client

return c.RunSmoketest()
return c.RunSmoketest(cmd.Context())
}

func AddSmoketestCmd(parent *cobra.Command, opts *util.GlobalOptions) {
Expand Down Expand Up @@ -113,8 +114,11 @@ func AddSmoketestCmd(parent *cobra.Command, opts *util.GlobalOptions) {
util.AddCmd(parent, c.cmd)
}

func (c *SmoketestCodesphereCmd) RunSmoketest() (err error) {
ctx, cancel := context.WithTimeout(context.Background(), c.Opts.Timeout)
// RunSmoketest runs the selected smoke test steps. The passed context bounds
// the run in addition to the configured timeout, so callers that orchestrate
// several tests (see the test command) can cancel it.
func (c *SmoketestCodesphereCmd) RunSmoketest(ctx context.Context) (err error) {
ctx, cancel := context.WithTimeout(ctx, c.Opts.Timeout)
defer cancel()

availableStepsMap := make(map[string]teststeps.SmokeTestStep)
Expand Down
36 changes: 19 additions & 17 deletions cli/cmd/codesphere/smoketest_codesphere_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package codesphere_test

import (
"context"
"fmt"
"strconv"
"strings"
Expand Down Expand Up @@ -124,7 +125,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
It("returns an error indicating no teams are available", func() {
mockClient.EXPECT().ListTeams("").Return([]api.Team{}, nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("no teams available")))
})
})
Expand All @@ -138,7 +139,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {

mockFullTestRun(mockClient, 99, 456, 789)

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(BeNil())
})
})
Expand All @@ -152,7 +153,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {

mockFullTestRun(mockClient, 21, 456, 789)

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(BeNil())
})
})
Expand All @@ -164,7 +165,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
It("returns an error indicating no workspace plans are available", func() {
mockClient.EXPECT().ListWorkspacePlans().Return([]api.WorkspacePlan{}, nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("no workspace plans available")))
})
})
Expand All @@ -176,13 +177,14 @@ var _ = Describe("SmoketestCodesphereCmd", func() {

mockFullTestRun(mockClient, teamIdInt, 42, 789)

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(BeNil())
})
})
It("completes successfully with all steps", func() {
mockFullTestRun(mockClient, teamIdInt, planIdInt, 789)
err := c.RunSmoketest()

err := c.RunSmoketest(context.Background())
Expect(err).To(BeNil())
})

Expand All @@ -194,7 +196,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
(*string)(nil), // empty workspace
).Return(0, fmt.Errorf("create failed")).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to create workspace")))
})

Expand All @@ -218,7 +220,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceID,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to set environment variable")))
})

Expand Down Expand Up @@ -248,7 +250,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to create ci.yml")))
})

Expand Down Expand Up @@ -291,7 +293,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to sync landscape")))
})

Expand Down Expand Up @@ -340,7 +342,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to start pipeline")))
})

Expand Down Expand Up @@ -394,7 +396,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("unexpected state")))
})

Expand Down Expand Up @@ -448,7 +450,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("unexpected state")))
})

Expand Down Expand Up @@ -501,7 +503,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
).Return(nil).Once()

opts.Timeout = 100 * time.Millisecond
err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("timed out")))
Expect(err).To(MatchError(ContainSubstring("connection refused")))
})
Expand Down Expand Up @@ -558,7 +560,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
).Return(nil).Once()

opts.Timeout = 100 * time.Millisecond
err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("timed out")))
})

Expand Down Expand Up @@ -614,7 +616,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
workspaceId,
).Return(fmt.Errorf("delete failed")).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(MatchError(ContainSubstring("failed to delete workspace")))
})

Expand All @@ -634,7 +636,7 @@ var _ = Describe("SmoketestCodesphereCmd", func() {
"smoketest",
).Return(nil).Once()

err := c.RunSmoketest()
err := c.RunSmoketest(context.Background())
Expect(err).To(BeNil())
})
})
Expand Down
87 changes: 87 additions & 0 deletions cli/cmd/codesphere/status_codesphere.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) Codesphere Inc.
// SPDX-License-Identifier: Apache-2.0

package codesphere

import (
"fmt"
"time"

csio "github.com/codesphere-cloud/cs-go/pkg/io"
"github.com/codesphere-cloud/oms/cli/cmd/util"
"github.com/codesphere-cloud/oms/internal/codesphere"
"github.com/spf13/cobra"
)

const (
defaultStatusTimeout = 5 * time.Minute
statusPollInterval = 5 * time.Second
)

// StatusCodesphereOpts configures the status report of a Codesphere installation.
type StatusCodesphereOpts struct {
BaseURL string
Token string
Wait bool
Timeout time.Duration
Client codesphere.Client
}

// StatusCodesphereCmd represents the status codesphere command.
type StatusCodesphereCmd struct {
cmd *cobra.Command
Opts *StatusCodesphereOpts
}

// RunE prints the status report and fails the command if the installation is not ready.
func (c *StatusCodesphereCmd) RunE(cmd *cobra.Command, _ []string) error {
client, err := codesphere.NewClient(c.Opts.BaseURL, c.Opts.Token)
if err != nil {
return fmt.Errorf("failed to create Codesphere client: %w", err)
}

c.Opts.Client = client

report := fetchStatus(cmd.Context(), c.Opts)
printStatus(cmd.OutOrStdout(), c.Opts.BaseURL, report)

if !report.Ready {
return fmt.Errorf("codesphere installation is not ready")
}

return nil
}

// AddStatusCmd adds the status codesphere command to the given parent command.
func AddStatusCmd(parent *cobra.Command, _ *util.GlobalOptions) {
c := StatusCodesphereCmd{
cmd: &cobra.Command{
Use: "codesphere",
Short: "Check the status of a Codesphere installation",
Long: csio.Long(`Check whether a Codesphere installation is reachable and ready to use,
by querying the Codesphere API.`),
Example: util.FormatExamples("status codesphere", []csio.Example{
{
Cmd: "--baseurl https://codesphere.example.com/api --token YOUR_TOKEN",
Desc: "Check the status of a Codesphere installation",
},
{
Cmd: "--baseurl https://codesphere.example.com/api --token YOUR_TOKEN --wait",
Desc: "Block and retry until the Codesphere installation is ready",
},
}),
},
Opts: &StatusCodesphereOpts{},
}
c.cmd.Flags().StringVar(&c.Opts.BaseURL, "baseurl", "", "Base URL of the Codesphere API")
c.cmd.Flags().StringVar(&c.Opts.Token, "token", "", "API token for authentication")
c.cmd.Flags().BoolVar(&c.Opts.Wait, "wait", false, "Block and retry until the installation is ready")
c.cmd.Flags().DurationVar(&c.Opts.Timeout, "timeout", defaultStatusTimeout, "Timeout when waiting for the installation to become ready")

util.MarkFlagRequired(c.cmd, "baseurl")
util.MarkFlagRequired(c.cmd, "token")

c.cmd.RunE = c.RunE

util.AddCmd(parent, c.cmd)
}
Loading
Loading