Skip to content
This repository has been archived by the owner on Jul 28, 2023. It is now read-only.

Commit

Permalink
Merge pull request #166 from tseelbach/nocoll
Browse files Browse the repository at this point in the history
Nocoll
  • Loading branch information
s1cyan authored Feb 7, 2020
2 parents 79e4dc7 + a63f61b commit d2419c0
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 78 deletions.
7 changes: 5 additions & 2 deletions cmd/deactivate.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
// deactivateCmd represents the deactivate command
var deactivateCmd = &cobra.Command{
Args: cobra.MinimumNArgs(1),
Use: "deactivate collection-name",
Use: "deactivate stack-name version",
Short: "Remove the specified collection from the list of available application types, without deleting it from the Kabanero instance.",
Long: `
Run the deactivate command to remove the specified collection from the list of available application types, without deleting it from the Kabanero instance.
Expand All @@ -34,15 +34,18 @@ This command is useful in a case where you have cloned a collection and customiz
RunE: func(cmd *cobra.Command, args []string) error {
// fmt.Println("deactivate called")
collectionName := args[0]
url := getRESTEndpoint("v1/collections/" + collectionName)
version := args[1]
url := getRESTEndpoint("v1/stacks/" + collectionName + "/versions/" + version)
resp, err := sendHTTPRequest("DELETE", url, nil)
if err != nil {
Debug.log("deactivate: Error on sendHTTPRequest:")
return err
}
data := make(map[string]interface{})

err = json.NewDecoder(resp.Body).Decode(&data)
if err != nil {
Debug.log("deactivate: Error on Decode:")
return err
}
deactivateResponse := data["status"]
Expand Down
119 changes: 73 additions & 46 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,92 +18,119 @@ package cmd
import (
"encoding/json"
"fmt"
"net/http"
// "net/http"
"os"
"strings"
"text/tabwriter"

"github.com/spf13/cobra"
)

// CollStruct : Each collection contains following information to be displayed
type CollStruct struct {
Name string
Version string
Status string
DesiredState string
// The list command gets a set of "stacks" back from the CLI Service.
// There are 2 distinct structs for the returned stacks:
// - KabStruct represents the JSON returned for the Kabanero stacks.
// - CommonStackStruct represents the JSON returned for all the other stacks.
type KabStruct struct {
Name string
Status []StatusStruct `json:"status"`
}
type StatusStruct struct {
Version string
Status string
}

type CommonStackStruct struct {
Name string
Versions []VersionStruct `json:"versions"`
}

// CollectionsResponse : all the collections
type CollectionsResponse struct {
NewColl []CollStruct `json:"new curated collections"`
ActivateColl []CollStruct `json:"activate collections"`
KabColl []CollStruct `json:"kabanero collections"`
ObsoleteColl []CollStruct `json:"obsolete collections"`
CuratedColl []CollStruct `json:"curated collections"`
VChangeColl []CollStruct `json:"version change collections"`
type VersionStruct struct {
Version string
Images []string `json:"image"`
}

// KabCollectionsHeader for all references to what we call the "Kab Collections"
var KabCollectionsHeader = "Kabanero Instance Collections"
// StacksResponse : all the stacks
type StacksResponse struct {
NewStack []CommonStackStruct `json:"new curated stacks"`
ActivateStack []CommonStackStruct `json:"activate stacks"`
KabStack []KabStruct `json:"kabanero stacks"`
ObsoleteStack []CommonStackStruct `json:"obsolete stacks"`
CuratedStack []CommonStackStruct `json:"curated stacks"`
}

// KabStacksHeader for all references to what we call the "Kab stacks"
var KabStacksHeader = "Kabanero Instance Stacks "

// GHCollectionsHeader for all references to the "curated collections"
var GHCollectionsHeader = "GitHub Curated Collections"
// GHStacksHeader for all references to the "curated stacks"
var GHStacksHeader = "GitHub Curated Stacks"

// listCmd represents the list command
var listCmd = &cobra.Command{
Use: "list ",
Short: "List all the collections in the kabanero instance, and their status",
Long: `List all the collections in the kabanero instance, and their status.
Modifications to the curated collection may be slow to replicate in git hub and therefore may not be reflected immediately in KABANERO LIST or SYNC display output`,
Short: "List all the stacks in the kabanero instance, and their status",
Long: `List all the stacks in the kabanero instance, and their status.
Modifications to the curated stack may be slow to replicate in git hub and therefore may not be reflected immediately in KABANERO LIST or SYNC display output`,
RunE: func(cmd *cobra.Command, args []string) error {
url := getRESTEndpoint("v1/collections")
Debug.log("List called...")
url := getRESTEndpoint("v1/stacks")
resp, err := sendHTTPRequest("GET", url, nil)
if err != nil {
Debug.log("list: Error on sendHTTPRequest:")
return err
}

Debug.log("RESPONSE ", url, resp.StatusCode, http.StatusText(resp.StatusCode))
// cannot reference resp here. May not be fully formed and cause nil pointer deref: Debug.log("RESPONSE ", url, resp.StatusCode, http.StatusText(resp.StatusCode))
//Decode the response into data
decoder := json.NewDecoder(resp.Body)
var data CollectionsResponse
var data StacksResponse
err = decoder.Decode(&data)
if err != nil {
Debug.log("list: Error on Decode:")
return err
}

Debug.log(data)
tWriter := new(tabwriter.Writer)
tWriter.Init(os.Stdout, 0, 8, 0, '\t', 0)

fmt.Fprintf(tWriter, "\n%s\t%s\t%s", KabCollectionsHeader, "Version", "Status")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", strings.Repeat("-", len(KabCollectionsHeader)), "-------", "------")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", KabStacksHeader, "Version", "Status")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", strings.Repeat("-", len(KabStacksHeader)), "-------", "------")

for i := 0; i < len(data.KabColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.KabColl[i].Name, data.KabColl[i].Version, data.KabColl[i].Status)
for i := 0; i < len(data.KabStack); i++ {
for j := 0; j < len(data.KabStack[i].Status); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.KabStack[i].Name, data.KabStack[i].Status[j].Version, data.KabStack[i].Status[j].Status)
}
}
for i := 0; i < len(data.ObsoleteColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ObsoleteColl[i].Name, data.ObsoleteColl[i].Version, "obsolete")
for i := 0; i < len(data.ObsoleteStack); i++ {
for j := 0; j < len(data.ObsoleteStack[i].Versions); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ObsoleteStack[i].Name, data.ObsoleteStack[i].Versions[j].Version, "obsolete")
}
}

fmt.Fprintln(tWriter)

tWriter.Flush()

// put new collections into a map to compare to curated
mNewColl := make(map[string]string)
for i := 0; i < len(data.NewColl); i++ {
mNewColl[data.NewColl[i].Name] = data.NewColl[i].Name + " *"
// put new stacks name/version into a map to compare to curated.
mNewStack := make(map[string]string)
for i := 0; i < len(data.NewStack); i++ {
for j := 0; j < len(data.NewStack[i].Versions); j++ {
mNewStack[data.NewStack[i].Name] = data.NewStack[i].Name + data.NewStack[i].Versions[j].Version
}
}

fmt.Fprintf(tWriter, "\n%s\t%s", GHCollectionsHeader, "Version")
fmt.Fprintf(tWriter, "\n%s\t%s", strings.Repeat("-", len(GHCollectionsHeader)), "-------")
for i := 0; i < len(data.CuratedColl); i++ {
name := data.CuratedColl[i].Name
if nameStarred, found := mNewColl[name]; found {
fmt.Fprintf(tWriter, "\n%s\t%s", nameStarred, data.CuratedColl[i].Version)
} else {
fmt.Fprintf(tWriter, "\n%s\t%s", name, data.CuratedColl[i].Version)
fmt.Fprintf(tWriter, "\n%s\t%s", GHStacksHeader, "Version")
fmt.Fprintf(tWriter, "\n%s\t%s", strings.Repeat("-", len(GHStacksHeader)), "-------")
for i := 0; i < len(data.CuratedStack); i++ {
name := data.CuratedStack[i].Name
for j := 0; j < len(data.CuratedStack[i].Versions); j++ {
version := data.CuratedStack[i].Versions[j].Version
nameAndVersion := name + version

//fmt.Fprintf(tWriter, "\n%s", name)
_, found := mNewStack[nameAndVersion]
if found {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", name, version, "new")
} else {
fmt.Fprintf(tWriter, "\n%s\t%s", name, version)
}
}
}
fmt.Fprintln(tWriter)
Expand Down
1 change: 1 addition & 0 deletions cmd/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ var loginCmd = &cobra.Command{

resp, err := sendHTTPRequest("POST", kabLoginURL, requestBody)
if err != nil {
Debug.log("login: Error on sendHTTPRequest:")
return err
}

Expand Down
16 changes: 8 additions & 8 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package cmd

//import collections "github.com/kabanero-command-line/kab-cli/kabanero/collections/cmd"
//import access "github.com/kabanero-command-line/kab-cli/kabanero/onboard/cmd"

import (
"flag"
"fmt"
Expand All @@ -14,8 +11,6 @@ import (
// for logging
"k8s.io/klog"

// homedir "github.com/mitchellh/go-homedir"

"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -29,9 +24,9 @@ var (
APIVersionV1 = "v1"
//dryrun bool
verbose bool
verboseHTTP bool
klogInitialized = false
KabURLKey = "KABURL"
KabURLContext = "KabCollections-1.0-SNAPSHOT"
)

func homeDir() string {
Expand All @@ -46,7 +41,7 @@ func homeDir() string {
var rootCmd = &cobra.Command{
Use: "kabanero",
Short: "This repo defines a command line interface used by the enterprise, solution, or application architect who defines and manages the kabanero collections that are used by developers to create governed applications for their business.",
Long: `**kabanero** is a command line interface for managing the collections in a Kabanero
Long: `**kabanero** is a command line interface for managing the stacks in a Kabanero
environment, as well as to on-board the people that will use
the environment to build applications.
Expand All @@ -69,7 +64,12 @@ func init() {
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.kabanero.yaml)")
// Added for logging
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Turns on debug output and logging to a file in $HOME/.kabanero/logs")

rootCmd.PersistentFlags().BoolVarP(&verboseHTTP, "debug http", "x", false, "Turns on debug output for http request/responses")
err := rootCmd.PersistentFlags().MarkHidden("debug http")
if err != nil {
fmt.Fprintln(os.Stdout, "err with MarkHidden")
}
//rootCmd.Execute()
// not implemented: rootCmd.PersistentFlags().BoolVar(&dryrun, "dryrun", false, "Turns on dry run mode")

// The subbcommand processor for commands to manage the apphub
Expand Down
71 changes: 49 additions & 22 deletions cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
"os"
"strings"
"text/tabwriter"
Expand Down Expand Up @@ -66,6 +67,15 @@ func sendHTTPRequest(method string, url string, jsonBody []byte) (*http.Response
return resp, errors.New("Login to your kabanero instance")
}
}

if verboseHTTP {
requestDump, err := httputil.DumpRequest(req, true)
if err != nil {
fmt.Println(err)
}
Info.log("requestDump: " + string(requestDump))
}

resp, err = client.Do(req)
if err != nil {
return resp, errors.New(err.Error())
Expand All @@ -84,16 +94,25 @@ func sendHTTPRequest(method string, url string, jsonBody []byte) (*http.Response
if resp.StatusCode == 401 {
return nil, errors.New("Your session may have expired or the credentials entered may be invalid")
}
if resp.StatusCode == 539 {
if resp.StatusCode == 539 || resp.StatusCode == 424 || resp.StatusCode == 500 {
message := make(map[string]interface{})
err = json.NewDecoder(resp.Body).Decode(&message)
if err != nil {
Debug.log("sync: Decode error for 500/539/424")
return nil, err
}
fmt.Println(message["message"].(string))
return nil, nil
fmt.Println("HTTP Status " + string(resp.StatusCode) + ": " + message["message"].(string))
return resp, errors.New("Invalid Response")
}
Debug.log("RESPONSE ", url, resp.StatusCode, http.StatusText(resp.StatusCode))

if verboseHTTP {
responseDump, err := httputil.DumpResponse(resp, true)
if err != nil {
fmt.Println(err)
}
Info.log("responseDump: " + string(responseDump))
}
Debug.log("RESPONSE ", url, " ", resp.StatusCode, " ", http.StatusText(resp.StatusCode))
return resp, nil
}

Expand All @@ -106,48 +125,56 @@ var syncCmd = &cobra.Command{
Modifications to the curated collection may be slow to replicate in git hub and therefore may not be reflected immediately in KABANERO LIST or SYNC display output
`,
RunE: func(cmd *cobra.Command, args []string) error {
url := getRESTEndpoint("v1/collections")
url := getRESTEndpoint("v1/stacks")
resp, err := sendHTTPRequest("PUT", url, nil)
if err != nil {
Debug.log("sync: Error on sendHTTPRequest:")
return errors.New(err.Error())
}
Debug.log("RESPONSE ", url, resp.StatusCode, http.StatusText(resp.StatusCode))
defer resp.Body.Close()
//Decode the response into data
decoder := json.NewDecoder(resp.Body)
var data CollectionsResponse
var data StacksResponse
err = decoder.Decode(&data)
if err != nil {
Debug.log("sync: Error on Decode:")
return err
}

Debug.log(data)
tWriter := new(tabwriter.Writer)
tWriter.Init(os.Stdout, 0, 8, 0, '\t', 0)
if len(data.NewColl) == 0 && (len(data.KabColl) == 0) && len(data.ObsoleteColl) == 0 && len(data.CuratedColl) == 0 && len(data.VChangeColl) == 0 && len(data.ActivateColl) == 0 {
syncedOutput := KabCollectionsHeader + " is already synchronized with the " + GHCollectionsHeader
if len(data.NewStack) == 0 && (len(data.KabStack) == 0) && len(data.ObsoleteStack) == 0 && len(data.CuratedStack) == 0 && len(data.ActivateStack) == 0 {
syncedOutput := KabStacksHeader + " is already synchronized with the " + GHStacksHeader
fmt.Println(strings.ToLower(syncedOutput))
} else {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", KabCollectionsHeader, "Version", "Status")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", strings.Repeat("-", len(KabCollectionsHeader)), "-------", "------")
for i := 0; i < len(data.NewColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.NewColl[i].Name, data.NewColl[i].Version, "added to kabanero")
}
for i := 0; i < len(data.ActivateColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ActivateColl[i].Name, data.ActivateColl[i].Version, "inactive ==> active")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", KabStacksHeader, "Version", "Status")
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", strings.Repeat("-", len(KabStacksHeader)), "-------", "------")

for i := 0; i < len(data.NewStack); i++ {
for j := 0; j < len(data.NewStack[i].Versions); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.NewStack[i].Name, data.NewStack[i].Versions[j].Version, "added to Kabanero")
}
}
for i := 0; i < len(data.KabColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.KabColl[i].Name, data.KabColl[i].Version, data.KabColl[i].Status)
for i := 0; i < len(data.ActivateStack); i++ {
for j := 0; j < len(data.ActivateStack[i].Versions); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ActivateStack[i].Name, data.ActivateStack[i].Versions[j].Version, "inactive ==> active")
}
}
for i := 0; i < len(data.ObsoleteColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ObsoleteColl[i].Name, data.ObsoleteColl[i].Version, "deactivated")
for i := 0; i < len(data.KabStack); i++ {
for j := 0; j < len(data.KabStack[i].Status); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.KabStack[i].Name, data.KabStack[i].Status[j].Version, data.KabStack[i].Status[j].Status)
}
}
for i := 0; i < len(data.VChangeColl); i++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.VChangeColl[i].Name, data.VChangeColl[i].Version, "version changed")
for i := 0; i < len(data.ObsoleteStack); i++ {
for j := 0; j < len(data.ObsoleteStack[i].Versions); j++ {
fmt.Fprintf(tWriter, "\n%s\t%s\t%s", data.ObsoleteStack[i].Name, data.ObsoleteStack[i].Versions[j].Version, "deactivated")
}
}

fmt.Fprintln(tWriter)
tWriter.Flush()

}
return nil
},
Expand Down
2 changes: 2 additions & 0 deletions vendor/github.com/spf13/viper/go.mod

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d2419c0

Please sign in to comment.