-
Notifications
You must be signed in to change notification settings - Fork 208
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
OCM-6527 | feat: add describe ingress command
- Loading branch information
Showing
9 changed files
with
481 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package ingress | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"regexp" | ||
|
||
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" | ||
"github.com/spf13/cobra" | ||
|
||
"github.com/openshift/rosa/pkg/ingress" | ||
"github.com/openshift/rosa/pkg/ocm" | ||
"github.com/openshift/rosa/pkg/output" | ||
"github.com/openshift/rosa/pkg/rosa" | ||
) | ||
|
||
const ( | ||
use = "ingress" | ||
short = "Show details of the specified ingress within cluster" | ||
example = `rosa describe ingress <ingress_id> -c mycluster` | ||
) | ||
|
||
// Regular expression to used to make sure that the identifier given by the | ||
// user is safe and that it there is no risk of SQL injection: | ||
var ingressKeyRE = regexp.MustCompile(`^[a-z0-9]{3,5}$`) | ||
|
||
func NewDescribeIngressCommand() *cobra.Command { | ||
options := NewDescribeIngressUserOptions() | ||
cmd := &cobra.Command{ | ||
Use: use, | ||
Short: short, | ||
Example: example, | ||
Run: rosa.DefaultRunner(rosa.RuntimeWithOCM(), DescribeIngressRunner(options)), | ||
Args: func(_ *cobra.Command, argv []string) error { | ||
if len(argv) != 1 { | ||
return fmt.Errorf( | ||
"Expected exactly one command line parameter containing the id of the ingress", | ||
) | ||
} | ||
return nil | ||
}, | ||
} | ||
|
||
flags := cmd.Flags() | ||
flags.StringVar( | ||
&options.ingress, | ||
"ingress", | ||
"", | ||
"Ingress of the cluster to target", | ||
) | ||
|
||
ocm.AddClusterFlag(cmd) | ||
output.AddFlag(cmd) | ||
return cmd | ||
} | ||
|
||
func DescribeIngressRunner(userOptions DescribeIngressUserOptions) rosa.CommandRunner { | ||
return func(_ context.Context, runtime *rosa.Runtime, cmd *cobra.Command, argv []string) error { | ||
options := NewDescribeIngressOptions() | ||
if len(argv) == 1 && !cmd.Flag("ingress").Changed { | ||
userOptions.ingress = argv[0] | ||
} else { | ||
err := cmd.ParseFlags(argv) | ||
if err != nil { | ||
return fmt.Errorf("unable to parse flags: %v", err) | ||
} | ||
} | ||
err := options.Bind(userOptions) | ||
if err != nil { | ||
return err | ||
} | ||
ingressKey := options.args.ingress | ||
if !ingressKeyRE.MatchString(ingressKey) { | ||
return fmt.Errorf( | ||
"ingress identifier %q isn't valid: it must contain only letters or digits", | ||
ingressKey, | ||
) | ||
} | ||
clusterKey := runtime.GetClusterKey() | ||
cluster := runtime.FetchCluster() | ||
if cluster.State() != cmv1.ClusterStateReady { | ||
return fmt.Errorf("cluster %q is not yet ready", clusterKey) | ||
} | ||
service := ingress.NewIngressService() | ||
return service.DescribeIngress(runtime, cluster, ingressKey) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package ingress | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
"github.com/onsi/gomega/format" | ||
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" | ||
. "github.com/openshift-online/ocm-sdk-go/testing" | ||
|
||
"github.com/openshift/rosa/pkg/aws" | ||
. "github.com/openshift/rosa/pkg/output" | ||
"github.com/openshift/rosa/pkg/test" | ||
) | ||
|
||
var _ = Describe("Describe ingress", func() { | ||
const ( | ||
ingressOutput = `Cluster ID: 123 | ||
Component Routes: | ||
console: | ||
Hostname: console-hostname | ||
TLS Secret Ref: console-secret | ||
downloads: | ||
Hostname: downloads-hostname | ||
TLS Secret Ref: downloads-secret | ||
oauth: | ||
Hostname: oauth-hostname | ||
TLS Secret Ref: oauth-secret | ||
Default: true | ||
Excluded Namespaces: [excluded-ns-1, excluded-ns-2] | ||
ID: a1b1 | ||
LB-Type: nlb | ||
Namespace Ownership Policy: Strict | ||
Private: false | ||
Route Selectors: map[route-1:selector-1 route-2:selector-2] | ||
Wildcard Policy: WildcardsAllowed | ||
` | ||
) | ||
Context("describe", func() { | ||
// Full diff for long string to help debugging | ||
format.TruncatedDiff = false | ||
|
||
mockReadyCluster := test.MockCluster(func(c *cmv1.ClusterBuilder) { | ||
c.ID("123") | ||
c.Region(cmv1.NewCloudRegion().ID(aws.DefaultRegion)) | ||
c.State(cmv1.ClusterStateReady) | ||
}) | ||
classicClusterReady := test.FormatClusterList([]*cmv1.Cluster{mockReadyCluster}) | ||
ingress, err := cmv1.NewIngress(). | ||
ID("a1b1"). | ||
Default(true). | ||
Listening(cmv1.ListeningMethodExternal). | ||
LoadBalancerType(cmv1.LoadBalancerFlavorNlb). | ||
RouteWildcardPolicy(cmv1.WildcardPolicyWildcardsAllowed). | ||
RouteNamespaceOwnershipPolicy(cmv1.NamespaceOwnershipPolicyStrict). | ||
RouteSelectors(map[string]string{ | ||
"route-1": "selector-1", | ||
"route-2": "selector-2", | ||
}). | ||
ExcludedNamespaces("excluded-ns-1", "excluded-ns-2"). | ||
ComponentRoutes(map[string]*cmv1.ComponentRouteBuilder{ | ||
"oauth": cmv1.NewComponentRoute().Hostname("oauth-hostname").TlsSecretRef("oauth-secret"), | ||
"downloads": cmv1.NewComponentRoute().Hostname("downloads-hostname").TlsSecretRef("downloads-secret"), | ||
"console": cmv1.NewComponentRoute().Hostname("console-hostname").TlsSecretRef("console-secret"), | ||
}).Build() | ||
Expect(err).To(BeNil()) | ||
ingressResponse := test.FormatIngressList([]*cmv1.Ingress{ingress}) | ||
var t *test.TestingRuntime | ||
BeforeEach(func() { | ||
t = test.NewTestRuntime() | ||
SetOutput("") | ||
}) | ||
|
||
It("Fails if ingress ID/alias has not been specified", func() { | ||
runner := DescribeIngressRunner(NewDescribeIngressUserOptions()) | ||
err := t.StdOutReader.Record() | ||
Expect(err).ToNot(HaveOccurred()) | ||
err = runner(context.Background(), t.RosaRuntime, NewDescribeIngressCommand(), []string{}) | ||
Expect(err).ToNot(BeNil()) | ||
Expect(err.Error()).To(ContainSubstring("you need to specify an ingress ID/alias")) | ||
}) | ||
|
||
It("Ingress not found", func() { | ||
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, classicClusterReady)) | ||
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusNotFound, "")) | ||
args := NewDescribeIngressUserOptions() | ||
args.ingress = "apps" | ||
runner := DescribeIngressRunner(args) | ||
err := t.StdOutReader.Record() | ||
Expect(err).ToNot(HaveOccurred()) | ||
err = runner(context.Background(), t.RosaRuntime, NewDescribeIngressCommand(), []string{ | ||
"-c", mockReadyCluster.ID(), | ||
}) | ||
Expect(err).ToNot(BeNil()) | ||
Expect(err.Error()).To(Equal("Failed to get ingress 'apps' for cluster '123'")) | ||
}) | ||
|
||
It("Ingress found", func() { | ||
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, classicClusterReady)) | ||
t.ApiServer.AppendHandlers(RespondWithJSON(http.StatusOK, ingressResponse)) | ||
args := NewDescribeIngressUserOptions() | ||
args.ingress = "apps" | ||
runner := DescribeIngressRunner(args) | ||
err := t.StdOutReader.Record() | ||
Expect(err).ToNot(HaveOccurred()) | ||
err = runner(context.Background(), t.RosaRuntime, NewDescribeIngressCommand(), []string{ | ||
"-c", mockReadyCluster.ID(), | ||
}) | ||
Expect(err).ToNot(HaveOccurred()) | ||
stdout, err := t.StdOutReader.Read() | ||
Expect(err).ToNot(HaveOccurred()) | ||
Expect(stdout).To(Equal(ingressOutput)) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package ingress | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo/v2" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestEditCluster(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Describe ingress suite") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package ingress | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/openshift/rosa/pkg/reporter" | ||
) | ||
|
||
type DescribeIngressUserOptions struct { | ||
ingress string | ||
} | ||
|
||
type DescribeIngressOptions struct { | ||
reporter *reporter.Object | ||
args DescribeIngressUserOptions | ||
} | ||
|
||
func NewDescribeIngressUserOptions() DescribeIngressUserOptions { | ||
return DescribeIngressUserOptions{ingress: ""} | ||
} | ||
|
||
func NewDescribeIngressOptions() *DescribeIngressOptions { | ||
return &DescribeIngressOptions{ | ||
reporter: reporter.CreateReporter(), | ||
args: NewDescribeIngressUserOptions(), | ||
} | ||
} | ||
|
||
func (i *DescribeIngressOptions) Ingress() string { | ||
return i.args.ingress | ||
} | ||
|
||
func (i *DescribeIngressOptions) Bind(args DescribeIngressUserOptions) error { | ||
if args.ingress == "" { | ||
return fmt.Errorf("you need to specify an ingress ID/alias") | ||
} | ||
i.args.ingress = args.ingress | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.