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  `