...

Source file src/k8s.io/kubectl/pkg/cmd/edit/testdata/record.go

Documentation: k8s.io/kubectl/pkg/cmd/edit/testdata

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"io"
    24  	"net/http"
    25  	"os"
    26  	"strings"
    27  
    28  	yaml "gopkg.in/yaml.v2"
    29  )
    30  
    31  type EditTestCase struct {
    32  	Description string `yaml:"description"`
    33  	// create or edit
    34  	Mode             string   `yaml:"mode"`
    35  	Args             []string `yaml:"args"`
    36  	Filename         string   `yaml:"filename"`
    37  	Output           string   `yaml:"outputFormat"`
    38  	Namespace        string   `yaml:"namespace"`
    39  	ExpectedStdout   []string `yaml:"expectedStdout"`
    40  	ExpectedStderr   []string `yaml:"expectedStderr"`
    41  	ExpectedExitCode int      `yaml:"expectedExitCode"`
    42  
    43  	Steps []EditStep `yaml:"steps"`
    44  }
    45  
    46  type EditStep struct {
    47  	// edit or request
    48  	StepType string `yaml:"type"`
    49  
    50  	// only applies to request
    51  	RequestMethod      string `yaml:"expectedMethod,omitempty"`
    52  	RequestPath        string `yaml:"expectedPath,omitempty"`
    53  	RequestContentType string `yaml:"expectedContentType,omitempty"`
    54  	Input              string `yaml:"expectedInput"`
    55  
    56  	// only applies to request
    57  	ResponseStatusCode int `yaml:"resultingStatusCode,omitempty"`
    58  
    59  	Output string `yaml:"resultingOutput"`
    60  }
    61  
    62  func main() {
    63  	tc := &EditTestCase{
    64  		Description:    "add a testcase description",
    65  		Mode:           "edit",
    66  		Args:           []string{"set", "args"},
    67  		ExpectedStdout: []string{"expected stdout substring"},
    68  		ExpectedStderr: []string{"expected stderr substring"},
    69  	}
    70  
    71  	var currentStep *EditStep
    72  
    73  	fmt.Println(http.ListenAndServe(":8081", http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
    74  
    75  		// Record non-discovery things
    76  		record := false
    77  		switch segments := strings.Split(strings.Trim(req.URL.Path, "/"), "/"); segments[0] {
    78  		case "api":
    79  			// api, version
    80  			record = len(segments) > 2
    81  		case "apis":
    82  			// apis, group, version
    83  			record = len(segments) > 3
    84  		case "callback":
    85  			record = true
    86  		}
    87  
    88  		body, err := io.ReadAll(req.Body)
    89  		checkErr(err)
    90  
    91  		switch m, p := req.Method, req.URL.Path; {
    92  		case m == "POST" && p == "/callback/in":
    93  			if currentStep != nil {
    94  				panic("cannot post input with step already in progress")
    95  			}
    96  			filename := fmt.Sprintf("%d.original", len(tc.Steps))
    97  			checkErr(os.WriteFile(filename, body, os.FileMode(0755)))
    98  			currentStep = &EditStep{StepType: "edit", Input: filename}
    99  		case m == "POST" && p == "/callback/out":
   100  			if currentStep == nil || currentStep.StepType != "edit" {
   101  				panic("cannot post output without posting input first")
   102  			}
   103  			filename := fmt.Sprintf("%d.edited", len(tc.Steps))
   104  			checkErr(os.WriteFile(filename, body, os.FileMode(0755)))
   105  			currentStep.Output = filename
   106  			tc.Steps = append(tc.Steps, *currentStep)
   107  			currentStep = nil
   108  		default:
   109  			if currentStep != nil {
   110  				panic("cannot make request with step already in progress")
   111  			}
   112  
   113  			urlCopy := *req.URL
   114  			urlCopy.Host = "localhost:8080"
   115  			urlCopy.Scheme = "http"
   116  			proxiedReq, err := http.NewRequest(req.Method, urlCopy.String(), bytes.NewReader(body))
   117  			checkErr(err)
   118  			proxiedReq.Header = req.Header
   119  			resp, err := http.DefaultClient.Do(proxiedReq)
   120  			checkErr(err)
   121  			defer resp.Body.Close()
   122  
   123  			bodyOut, err := io.ReadAll(resp.Body)
   124  			checkErr(err)
   125  
   126  			for k, vs := range resp.Header {
   127  				for _, v := range vs {
   128  					w.Header().Add(k, v)
   129  				}
   130  			}
   131  			w.WriteHeader(resp.StatusCode)
   132  			w.Write(bodyOut)
   133  
   134  			if record {
   135  				infile := fmt.Sprintf("%d.request", len(tc.Steps))
   136  				outfile := fmt.Sprintf("%d.response", len(tc.Steps))
   137  				checkErr(os.WriteFile(infile, tryIndent(body), os.FileMode(0755)))
   138  				checkErr(os.WriteFile(outfile, tryIndent(bodyOut), os.FileMode(0755)))
   139  				tc.Steps = append(tc.Steps, EditStep{
   140  					StepType:           "request",
   141  					Input:              infile,
   142  					Output:             outfile,
   143  					RequestContentType: req.Header.Get("Content-Type"),
   144  					RequestMethod:      req.Method,
   145  					RequestPath:        req.URL.Path,
   146  					ResponseStatusCode: resp.StatusCode,
   147  				})
   148  			}
   149  		}
   150  
   151  		tcData, err := yaml.Marshal(tc)
   152  		checkErr(err)
   153  		checkErr(os.WriteFile("test.yaml", tcData, os.FileMode(0755)))
   154  	})))
   155  }
   156  
   157  func checkErr(err error) {
   158  	if err != nil {
   159  		panic(err)
   160  	}
   161  }
   162  
   163  func tryIndent(data []byte) []byte {
   164  	indented := &bytes.Buffer{}
   165  	if err := json.Indent(indented, data, "", "\t"); err == nil {
   166  		return indented.Bytes()
   167  	}
   168  	return data
   169  }
   170  

View as plain text