This repository has been archived by the owner on Aug 27, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new account subcommand 'orgs', lists organizations: SREP-1736
- Loading branch information
alima
committed
Jul 19, 2019
1 parent
6a3ca17
commit b1426a7
Showing
3 changed files
with
270 additions
and
0 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,179 @@ | ||
/* | ||
Copyright (c) 2019 Red Hat, Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package orgs | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"strings" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/openshift-online/uhc-cli/pkg/config" | ||
flags "github.com/openshift-online/uhc-cli/pkg/flags" | ||
table "github.com/openshift-online/uhc-cli/pkg/table" | ||
amv1 "github.com/openshift-online/uhc-sdk-go/pkg/client/accountsmgmt/v1" | ||
) | ||
|
||
var args struct { | ||
columns string | ||
parameter []string | ||
padding int | ||
} | ||
|
||
// Cmd ... | ||
var Cmd = &cobra.Command{ | ||
Use: "orgs", | ||
Short: "List organizations.", | ||
Long: "Display a list of organizations.", | ||
Run: run, | ||
} | ||
|
||
func init() { | ||
// Add flags to rootCmd: | ||
fs := Cmd.Flags() | ||
flags.AddParameterFlag(fs, &args.parameter) | ||
fs.StringVar( | ||
&args.columns, | ||
"columns", | ||
"id,href,name", // Default value gets assigned later as connection is needed. | ||
"Organization identifier. Defaults to the organization of the current user.", | ||
) | ||
fs.IntVar( | ||
&args.padding, | ||
"padding", | ||
45, | ||
"Takes padding for custom columns, default to 45.", | ||
) | ||
} | ||
|
||
func run(cmd *cobra.Command, argv []string) { | ||
|
||
// Load the configuration file: | ||
cfg, err := config.Load() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Can't load config file: %v\n", err) | ||
os.Exit(1) | ||
} | ||
if cfg == nil { | ||
fmt.Fprintf(os.Stderr, "Not logged in, run the 'login' command\n") | ||
os.Exit(1) | ||
} | ||
|
||
// Check that the configuration has credentials or tokens that haven't have expired: | ||
armed, err := cfg.Armed() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Can't check if tokens have expired: %v\n", err) | ||
os.Exit(1) | ||
} | ||
if !armed { | ||
fmt.Fprintf(os.Stderr, "Tokens have expired, run the 'login' command\n") | ||
os.Exit(1) | ||
} | ||
|
||
// Create the connection, and remember to close it: | ||
connection, err := cfg.Connection() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Can't create connection: %v\n", err) | ||
os.Exit(1) | ||
} | ||
defer connection.Close() | ||
|
||
// Indices | ||
pageIndex := 1 | ||
pageSize := 100 | ||
|
||
// Setting column names and padding size | ||
// Update our column name displaying variable: | ||
args.columns = strings.Replace(args.columns, " ", "", -1) | ||
colUpper := strings.ToUpper(args.columns) | ||
colUpper = strings.Replace(colUpper, ".", " ", -1) | ||
columnNames := strings.Split(colUpper, ",") | ||
paddingByColumn := []int{29, 65, 70} | ||
if args.columns != "id,href,name" { | ||
paddingByColumn = []int{args.padding} | ||
} | ||
|
||
// Print Header Row: | ||
table.PrintPadded(os.Stdout, columnNames, paddingByColumn) | ||
fmt.Println() | ||
|
||
for { | ||
// Next page request: | ||
request := connection.AccountsMgmt().V1().Organizations(). | ||
List(). | ||
Page(pageIndex). | ||
Size(pageSize) | ||
|
||
// Apply parameters | ||
flags.ApplyParameterFlag(request, args.parameter) | ||
|
||
// Fetch next page | ||
orgList, err := request.Send() | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to retrieve organization list: %v\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Display organization information | ||
orgList.Items().Each(func(org *amv1.Organization) bool { | ||
// String to output marshal - | ||
// Map used to parse Organization data - | ||
// Writer to body variable: | ||
var body string | ||
var jsonBody map[string]interface{} | ||
boddyBuffer := bytes.NewBufferString(body) | ||
|
||
// Write Organization data to body variable: | ||
err := amv1.MarshalOrganization(org, boddyBuffer) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to marshal organization into byte buffer: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Get JSON from Organization bytes | ||
err = json.Unmarshal(boddyBuffer.Bytes(), &jsonBody) | ||
if err != nil { | ||
fmt.Fprintf(os.Stderr, "Failed to turn organization bytes into JSON map: %s\n", err) | ||
os.Exit(1) | ||
} | ||
|
||
// Loop through wanted columns and populate an organization instance | ||
iter := strings.Split(args.columns, ",") | ||
thisOrg := []string{} | ||
for _, element := range iter { | ||
value, status := table.FindMapValue(jsonBody, element) | ||
if !status { | ||
value = "NONE" | ||
} | ||
thisOrg = append(thisOrg, value) | ||
} | ||
table.PrintPadded(os.Stdout, thisOrg, paddingByColumn) | ||
return true | ||
}) | ||
|
||
// Break if we reach last page | ||
if orgList.Size() < pageSize { | ||
break | ||
} | ||
|
||
pageIndex++ | ||
} | ||
fmt.Println() | ||
} |
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,88 @@ | ||
/* | ||
Copyright (c) 2019 Red Hat, Inc. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
// This file contains functions that help displaying information in a tabular form | ||
|
||
package table | ||
|
||
import ( | ||
"fmt" | ||
"io" | ||
"strings" | ||
) | ||
|
||
// FindMapValue will find a key and retrieve its value from the given map. The key has to be | ||
// a string and can be multilayered, for example `foo.bar`. Returns the value and a boolean | ||
// indicating if the value was found. | ||
func FindMapValue(data map[string]interface{}, key string) (string, bool) { | ||
|
||
// Split key into array | ||
keys := strings.Split(key, ".") | ||
|
||
// loop though elements in sliced string: | ||
for _, element := range keys { | ||
|
||
// if key is found, continue: | ||
if val, ok := data[element]; ok { | ||
|
||
switch typed := val.(type) { | ||
|
||
// If key points to interface insance: | ||
case map[string]interface{}: | ||
data = typed | ||
|
||
// If key points to an end value: | ||
default: | ||
return fmt.Sprintf("%v", typed), true | ||
|
||
} | ||
|
||
} else { // Key not in map | ||
return "", false | ||
} | ||
} | ||
|
||
return "", false | ||
} | ||
|
||
// PrintPadded turns an array into a padded string and outputs it into the given writer. | ||
func PrintPadded(w io.Writer, columns []string, padding []int) { | ||
updated := updateRowPad(columns, padding) | ||
var finalString string | ||
for _, str := range updated { | ||
finalString = fmt.Sprint(finalString, str) | ||
} | ||
fmt.Fprint(w, finalString+"\n") | ||
} | ||
|
||
func updateRowPad(columnList []string, columnPad []int) []string { | ||
st := columnList | ||
fixLen := len(columnPad) - len(st) | ||
if fixLen < 0 { | ||
valueToUse := columnPad[len(columnPad)-1] | ||
for i := 0; i < fixLen*(-1); i++ { | ||
columnPad = append(columnPad, valueToUse) | ||
} | ||
} | ||
for i := range st { | ||
if len(st[i]) < columnPad[i] { | ||
st[i] = st[i] + strings.Repeat(" ", columnPad[i]-len(st[i])) | ||
} else { | ||
st[i] = st[i][:columnPad[i]-2] + " " | ||
} | ||
} | ||
return st | ||
} |