Skip to content
Open
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
123 changes: 100 additions & 23 deletions internal/cmd/skupper/link/kube/link_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type CmdLinkStatus struct {
Namespace string
output string
linkName string
siteName string
}

func NewCmdLinkStatus() *CmdLinkStatus {
Expand All @@ -47,8 +48,9 @@ func (cmd *CmdLinkStatus) ValidateInput(args []string) error {

if siteList == nil || len(siteList.Items) == 0 || err != nil {
validationErrors = append(validationErrors, fmt.Errorf("there is no skupper site available"))
} else if len(siteList.Items) == 1 {
cmd.siteName = siteList.Items[0].Name
}

if len(args) > 1 {
validationErrors = append(validationErrors, fmt.Errorf("this command only accepts one argument"))
}
Expand All @@ -70,58 +72,74 @@ func (cmd *CmdLinkStatus) ValidateInput(args []string) error {
func (cmd *CmdLinkStatus) InputToOptions() {
cmd.output = cmd.Flags.Output
}

func (cmd *CmdLinkStatus) Run() error {

if cmd.linkName != "" {

// display outgoing links
selectedLink, err := cmd.Client.Links(cmd.Namespace).Get(context.TODO(), cmd.linkName, metav1.GetOptions{})
if err != nil {
return err
if err == nil {
if cmd.output != "" {
return printEncodedOutput(cmd.output, selectedLink)
} else {
displaySingleLink(selectedLink)
}
}

if cmd.output != "" {
return printEncodedOuptut(cmd.output, selectedLink)
} else {
displaySingleLink(selectedLink)
// display incoming links
currentSite, err := cmd.Client.Sites(cmd.Namespace).Get(context.TODO(), cmd.siteName, metav1.GetOptions{})
if err == nil && currentSite != nil {
if cmd.output != "" {
printEncodedIncomingLink(currentSite, cmd.siteName, cmd.linkName, cmd.output)
} else {
displaySingleIncomingLink(currentSite, cmd.siteName, cmd.linkName)
}
}

} else {

// display outgoing links
linkList, err := cmd.Client.Links(cmd.Namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return err
}

if linkList != nil && len(linkList.Items) == 0 {
fmt.Println("There are no link resources in the namespace")
return nil
}

if cmd.output != "" {
for _, link := range linkList.Items {
err := printEncodedOuptut(cmd.output, &link)
fmt.Println("There are no outgoing link resources in the namespace")
} else {
if cmd.output != "" {
for _, link := range linkList.Items {
err := printEncodedOutput(cmd.output, &link)

if err != nil {
return err
if err != nil {
return err
}
}
} else {
displayLinkList(linkList.Items)
}
} else {
displayLinkList(linkList.Items)
}

// display incoming links
currentSite, err := cmd.Client.Sites(cmd.Namespace).Get(context.TODO(), cmd.siteName, metav1.GetOptions{})
if err == nil && currentSite != nil {
if cmd.output != "" {
printEncodedIncomingLink(currentSite, cmd.siteName, "", cmd.output)
} else {
displayIncomingLink(currentSite, cmd.siteName)
}
}
}

return nil
}
func (cmd *CmdLinkStatus) WaitUntil() error { return nil }

func printEncodedOuptut(outputType string, link *v2alpha1.Link) error {
func printEncodedOutput(outputType string, link *v2alpha1.Link) error {
encodedOutput, err := utils.Encode(outputType, link)
fmt.Println(encodedOutput)
return err
}

func displaySingleLink(link *v2alpha1.Link) {
fmt.Println("Outgoing link from this site:")
fmt.Printf("%s\t: %s\n", "Name", link.Name)
fmt.Printf("%s\t: %s\n", "Status", link.Status.StatusType)
fmt.Printf("%s\t: %d\n", "Cost", link.Spec.Cost)
Expand All @@ -130,6 +148,7 @@ func displaySingleLink(link *v2alpha1.Link) {

func displayLinkList(linkList []v2alpha1.Link) {
writer := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
fmt.Println("Outgoing link from this site:")
fmt.Fprintln(writer, "NAME\tSTATUS\tCOST\tMESSAGE")

for _, link := range linkList {
Expand All @@ -139,3 +158,61 @@ func displayLinkList(linkList []v2alpha1.Link) {

writer.Flush()
}

func displayIncomingLink(currentSite *v2alpha1.Site, localSiteName string) {
incomingLinksFound := false
writer := tabwriter.NewWriter(os.Stdout, 0, 8, 1, '\t', tabwriter.AlignRight)
fmt.Fprintln(writer, "\nIncoming Links from remote sites: ")
for _, links := range currentSite.Status.Network {
for _, link := range links.Links {
if link.RemoteSiteName == localSiteName {
if !incomingLinksFound {
fmt.Fprintln(writer, "NAME\tSTATUS\tREMOTE SITE")
}
status := "Error"
if link.Operational {
status = "Ready"
}
fmt.Fprintf(writer, "%s\t%s\t%s", link.Name, status, links.Name)
fmt.Fprintln(writer)
incomingLinksFound = true
}
}
}

if !incomingLinksFound {
fmt.Fprintln(writer, "There are no incoming link resources in the namespace")
}

writer.Flush()
}

func displaySingleIncomingLink(currentSite *v2alpha1.Site, localSiteName string, linkName string) {
fmt.Println("\nIncoming Links from remote sites: ")
for _, links := range currentSite.Status.Network {
for _, link := range links.Links {
if link.RemoteSiteName == localSiteName && link.Name == linkName {
status := "Error"
if link.Operational {
status = "Ready"
}
fmt.Printf("%s\t: %s\n", "Name", link.Name)
fmt.Printf("%s\t: %s\n", "Status", status)
fmt.Printf("%s\t: %s\n", "Remote", links.Name)
}
}
}
}

func printEncodedIncomingLink(currentSite *v2alpha1.Site, localSiteName string, linkName string, outputType string) {
for _, links := range currentSite.Status.Network {
for _, link := range links.Links {
if link.RemoteSiteName == localSiteName {
if linkName == "" || link.Name == linkName {
encodedOutput, _ := utils.Encode(outputType, links)
fmt.Println(encodedOutput)
}
}
}
}
}
174 changes: 174 additions & 0 deletions internal/cmd/skupper/link/kube/link_status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ func TestCmdLinkStatus_Run(t *testing.T) {
errorMessage string
linkName string
output string
site string
}

testTable := []test{
Expand Down Expand Up @@ -231,13 +232,186 @@ func TestCmdLinkStatus_Run(t *testing.T) {
output: "unsupported",
errorMessage: "format unsupported not supported",
},
{
name: "runs ok no incoming links",
skupperObjects: []runtime.Object{
&v2alpha1.Site{
ObjectMeta: v1.ObjectMeta{
Name: "public1",
Namespace: "test",
},
Status: v2alpha1.SiteStatus{
Status: v2alpha1.Status{
Message: "OK",
},
},
},
},
site: "public1",
},
{
name: "runs ok shows incoming links",
skupperObjects: []runtime.Object{
&v2alpha1.Site{
ObjectMeta: v1.ObjectMeta{
Name: "public1",
Namespace: "test",
},
Status: v2alpha1.SiteStatus{
Status: v2alpha1.Status{
Message: "OK",
},
Network: []v2alpha1.SiteRecord{
{
Id: "08b068e0-31d2-4739-8291-d168230b527b",
Links: []v2alpha1.LinkRecord{
{
Name: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
Operational: true,
RemoteSiteId: "bb96fff0-2f25-4259-830a-b4c15e5b3f80",
RemoteSiteName: "public1",
},
},
Name: "public2",
Namespace: "public2",
Platform: "kubernetes",
Version: "2.0.0",
},
},
},
},
},
site: "public1",
},
{
name: "runs ok shows selected incoming link",
skupperObjects: []runtime.Object{
&v2alpha1.Site{
ObjectMeta: v1.ObjectMeta{
Name: "public1",
Namespace: "test",
},
Status: v2alpha1.SiteStatus{
Status: v2alpha1.Status{
Message: "OK",
},
Network: []v2alpha1.SiteRecord{
{
Id: "08b068e0-31d2-4739-8291-d168230b527b",
Links: []v2alpha1.LinkRecord{
{
Name: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
Operational: true,
RemoteSiteId: "bb96fff0-2f25-4259-830a-b4c15e5b3f80",
RemoteSiteName: "public1",
},
},
Name: "public2",
Namespace: "public2",
Platform: "kubernetes",
Version: "2.0.0",
},
},
},
},
},
linkName: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
site: "public1",
},
{
name: "runs ok shows selected incoming link in yaml form",
skupperObjects: []runtime.Object{
&v2alpha1.Site{
ObjectMeta: v1.ObjectMeta{
Name: "public1",
Namespace: "test",
},
Status: v2alpha1.SiteStatus{
Status: v2alpha1.Status{
Message: "OK",
},
Network: []v2alpha1.SiteRecord{
{
Id: "08b068e0-31d2-4739-8291-d168230b527b",
Links: []v2alpha1.LinkRecord{
{
Name: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
Operational: true,
RemoteSiteId: "bb96fff0-2f25-4259-830a-b4c15e5b3f80",
RemoteSiteName: "public1",
},
},
Name: "public2",
Namespace: "public2",
Platform: "kubernetes",
Version: "2.0.0",
},
},
},
},
},
linkName: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
site: "public1",
output: "yaml",
},
{
name: "runs ok shows incoming links in json",
skupperObjects: []runtime.Object{
&v2alpha1.Site{
ObjectMeta: v1.ObjectMeta{
Name: "public1",
Namespace: "test",
},
Status: v2alpha1.SiteStatus{
Status: v2alpha1.Status{
Message: "OK",
},
Network: []v2alpha1.SiteRecord{
{
Id: "08b068e0-31d2-4739-8291-d168230b527b",
Links: []v2alpha1.LinkRecord{
{
Name: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
Operational: true,
RemoteSiteId: "bb96fff0-2f25-4259-830a-b4c15e5b3f80",
RemoteSiteName: "public1",
},
},
Name: "public2",
Namespace: "public2",
Platform: "kubernetes",
Version: "2.0.0",
},
{
Id: "65816e8e-cf73-4ba7-91e9-e16a9c0b6ea4",
Links: []v2alpha1.LinkRecord{
{
Name: "public1-d72cbb23-d98d-4cf7-a943-a56d0d447498",
Operational: true,
RemoteSiteId: "bb96fff0-2f25-4259-830a-b4c15e5b3f80",
RemoteSiteName: "public1",
},
},
Name: "private1",
Namespace: "private1",
Platform: "kubernetes",
Version: "2.0.0",
},
},
},
},
},
site: "public1",
output: "yaml",
},
}

for _, test := range testTable {
cmd, err := newCmdLinkStatusWithMocks("test", nil, test.skupperObjects, test.skupperErrorMessage)
assert.Assert(t, err)
cmd.linkName = test.linkName
cmd.output = test.output
cmd.siteName = test.site

t.Run(test.name, func(t *testing.T) {

Expand Down