github.com/spinnaker/spin@v1.30.0/cmd/account/get_test.go (about) 1 // Copyright 2019 New Relic Corporation. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package account 16 17 import ( 18 "bytes" 19 "fmt" 20 "io/ioutil" 21 "net/http" 22 "net/http/httptest" 23 "strings" 24 "testing" 25 26 "github.com/nsf/jsondiff" 27 28 "github.com/andreyvit/diff" 29 30 "github.com/spinnaker/spin/cmd" 31 "github.com/spinnaker/spin/util" 32 ) 33 34 // testGateFail spins up a local http server that we will configure the GateClient 35 // to direct requests to. Responds with a 500 InternalServerError. 36 func testGateFail() *httptest.Server { 37 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 38 // TODO(jacobkiefer): Mock more robust errors once implemented upstream. 39 http.Error(w, "Internal Server Error", http.StatusInternalServerError) 40 })) 41 } 42 43 const ( 44 ACCOUNT = "account" 45 ) 46 47 func TestAccountGet_json(t *testing.T) { 48 ts := testGateAccountGetSuccess() 49 defer ts.Close() 50 51 buffer := new(bytes.Buffer) 52 rootCmd, rootOpts := cmd.NewCmdRoot(buffer, buffer) 53 rootCmd.AddCommand(NewAccountCmd(rootOpts)) 54 55 args := []string{"account", "get", ACCOUNT, "--gate-endpoint=" + ts.URL} 56 rootCmd.SetArgs(args) 57 err := rootCmd.Execute() 58 if err != nil { 59 t.Fatalf("Command failed with: %s", err) 60 } 61 62 expected := strings.TrimSpace(accountJson) 63 recieved := strings.TrimSpace(buffer.String()) 64 if expected != recieved { 65 opts := jsondiff.DefaultJSONOptions() 66 eq, d := jsondiff.Compare([]byte(expected), []byte(recieved), &opts) 67 if eq != jsondiff.FullMatch { 68 t.Fatalf("Unexpected command output:\n%s", d) 69 } 70 } 71 } 72 73 func TestAccountGet_yaml(t *testing.T) { 74 ts := testGateAccountGetSuccess() 75 defer ts.Close() 76 77 buffer := new(bytes.Buffer) 78 rootCmd, rootOpts := cmd.NewCmdRoot(buffer, buffer) 79 rootCmd.AddCommand(NewAccountCmd(rootOpts)) 80 81 args := []string{"account", "get", ACCOUNT, "--output", "yaml", "--gate-endpoint=" + ts.URL} 82 rootCmd.SetArgs(args) 83 err := rootCmd.Execute() 84 if err != nil { 85 t.Fatalf("Command failed with: %s", err) 86 } 87 88 expected := strings.TrimSpace(accountYaml) 89 recieved := strings.TrimSpace(buffer.String()) 90 if expected != recieved { 91 t.Fatalf("Unexpected command output:\n%s", diff.LineDiff(expected, recieved)) 92 } 93 } 94 95 func TestAccountGet_flags(t *testing.T) { 96 ts := testGateAccountGetSuccess() 97 defer ts.Close() 98 99 rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard) 100 rootCmd.AddCommand(NewAccountCmd(rootOpts)) 101 102 args := []string{"account", "get", "--gate-endpoint", ts.URL} // Missing positional arg. 103 rootCmd.SetArgs(args) 104 err := rootCmd.Execute() 105 if err == nil { // Success is actually failure here, flags are malformed. 106 t.Fatalf("Command failed with: %s", err) 107 } 108 } 109 110 func TestAccountGet_fail(t *testing.T) { 111 ts := testGateFail() 112 defer ts.Close() 113 114 rootCmd, rootOpts := cmd.NewCmdRoot(ioutil.Discard, ioutil.Discard) 115 rootCmd.AddCommand(NewAccountCmd(rootOpts)) 116 117 args := []string{"account", "get", ACCOUNT, "--gate-endpoint=" + ts.URL} 118 rootCmd.SetArgs(args) 119 err := rootCmd.Execute() 120 if err == nil { // Success is actually failure here, return payload is malformed. 121 t.Fatalf("Command failed with: %d", err) 122 } 123 } 124 125 // testGateAccountGetSuccess spins up a local http server that we will configure the GateClient 126 // to direct requests to. Responds with a 200 and a well-formed pipeline list. 127 func testGateAccountGetSuccess() *httptest.Server { 128 mux := util.TestGateMuxWithVersionHandler() 129 mux.Handle("/credentials/"+ACCOUNT, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 130 w.Header().Add("content-type", "application/json") 131 fmt.Fprintln(w, strings.TrimSpace(accountJson)) 132 })) 133 return httptest.NewServer(mux) 134 } 135 136 const accountJson = ` 137 { 138 "type": "kubernetes", 139 "cloudProvider": "kubernetes", 140 "accountType": "self", 141 "name": "account", 142 "environment": "self" 143 } 144 ` 145 146 // sorted fields 147 const accountYaml = ` 148 accountType: self 149 cloudProvider: kubernetes 150 environment: self 151 name: account 152 type: kubernetes 153 `