sigs.k8s.io/kubebuilder/v3@v3.14.0/test/e2e/utils/kubectl.go (about)

     1  /*
     2  Copyright 2019 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 utils
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"os/exec"
    23  	"strconv"
    24  	"strings"
    25  )
    26  
    27  // Kubectl contains context to run kubectl commands
    28  type Kubectl struct {
    29  	*CmdContext
    30  	Namespace      string
    31  	ServiceAccount string
    32  }
    33  
    34  // Command is a general func to run kubectl commands
    35  func (k *Kubectl) Command(cmdOptions ...string) (string, error) {
    36  	cmd := exec.Command("kubectl", cmdOptions...)
    37  	output, err := k.Run(cmd)
    38  	return string(output), err
    39  }
    40  
    41  // WithInput is a general func to run kubectl commands with input
    42  func (k *Kubectl) WithInput(stdinInput string) *Kubectl {
    43  	k.Stdin = strings.NewReader(stdinInput)
    44  	return k
    45  }
    46  
    47  // CommandInNamespace is a general func to run kubectl commands in the namespace
    48  func (k *Kubectl) CommandInNamespace(cmdOptions ...string) (string, error) {
    49  	if len(k.Namespace) == 0 {
    50  		return "", errors.New("namespace should not be empty")
    51  	}
    52  	return k.Command(append([]string{"-n", k.Namespace}, cmdOptions...)...)
    53  }
    54  
    55  // Apply is a general func to run kubectl apply commands
    56  func (k *Kubectl) Apply(inNamespace bool, cmdOptions ...string) (string, error) {
    57  	ops := append([]string{"apply"}, cmdOptions...)
    58  	if inNamespace {
    59  		return k.CommandInNamespace(ops...)
    60  	}
    61  	return k.Command(ops...)
    62  }
    63  
    64  // Get is a func to run kubectl get commands
    65  func (k *Kubectl) Get(inNamespace bool, cmdOptions ...string) (string, error) {
    66  	ops := append([]string{"get"}, cmdOptions...)
    67  	if inNamespace {
    68  		return k.CommandInNamespace(ops...)
    69  	}
    70  	return k.Command(ops...)
    71  }
    72  
    73  // Delete is a func to run kubectl delete commands
    74  func (k *Kubectl) Delete(inNamespace bool, cmdOptions ...string) (string, error) {
    75  	ops := append([]string{"delete"}, cmdOptions...)
    76  	if inNamespace {
    77  		return k.CommandInNamespace(ops...)
    78  	}
    79  	return k.Command(ops...)
    80  }
    81  
    82  // Logs is a func to run kubectl logs commands
    83  func (k *Kubectl) Logs(cmdOptions ...string) (string, error) {
    84  	ops := append([]string{"logs"}, cmdOptions...)
    85  	return k.CommandInNamespace(ops...)
    86  }
    87  
    88  // Wait is a func to run kubectl wait commands
    89  func (k *Kubectl) Wait(inNamespace bool, cmdOptions ...string) (string, error) {
    90  	ops := append([]string{"wait"}, cmdOptions...)
    91  	if inNamespace {
    92  		return k.CommandInNamespace(ops...)
    93  	}
    94  	return k.Command(ops...)
    95  }
    96  
    97  // VersionInfo holds a subset of client/server version information.
    98  type VersionInfo struct {
    99  	Major      string `json:"major"`
   100  	Minor      string `json:"minor"`
   101  	GitVersion string `json:"gitVersion"`
   102  
   103  	// Leaving major/minor int fields unexported prevents them from being set
   104  	// while leaving their exported counterparts untouched -> incorrect marshaled format.
   105  	major, minor uint64
   106  }
   107  
   108  // GetMajorInt returns the uint64 representation of vi.Major.
   109  func (vi VersionInfo) GetMajorInt() uint64 { return vi.major }
   110  
   111  // GetMinorInt returns the uint64 representation of vi.Minor.
   112  func (vi VersionInfo) GetMinorInt() uint64 { return vi.minor }
   113  
   114  func (vi *VersionInfo) parseVersionInts() (err error) {
   115  	if vi.Major != "" {
   116  		if vi.major, err = strconv.ParseUint(vi.Major, 10, 64); err != nil {
   117  			return err
   118  		}
   119  	}
   120  	if vi.Minor != "" {
   121  		if vi.minor, err = strconv.ParseUint(vi.Minor, 10, 64); err != nil {
   122  			return err
   123  		}
   124  	}
   125  	return nil
   126  }
   127  
   128  // KubernetesVersion holds a subset of both client and server versions.
   129  type KubernetesVersion struct {
   130  	ClientVersion VersionInfo `json:"clientVersion,omitempty"`
   131  	ServerVersion VersionInfo `json:"serverVersion,omitempty"`
   132  }
   133  
   134  func (v *KubernetesVersion) prepare() error {
   135  	if err := v.ClientVersion.parseVersionInts(); err != nil {
   136  		return err
   137  	}
   138  	if err := v.ServerVersion.parseVersionInts(); err != nil {
   139  		return err
   140  	}
   141  	return nil
   142  }
   143  
   144  // Version is a func to run kubectl version command
   145  func (k *Kubectl) Version() (ver KubernetesVersion, err error) {
   146  	out, err := k.Command("version", "-o", "json")
   147  	if err != nil {
   148  		return KubernetesVersion{}, err
   149  	}
   150  	if err := ver.decode(out); err != nil {
   151  		return KubernetesVersion{}, err
   152  	}
   153  	return ver, nil
   154  }
   155  
   156  func (v *KubernetesVersion) decode(out string) (err error) {
   157  	dec := json.NewDecoder(strings.NewReader(out))
   158  	if err := dec.Decode(&v); err != nil {
   159  		return err
   160  	}
   161  	if err := v.prepare(); err != nil {
   162  		return err
   163  	}
   164  	return nil
   165  }