Compare commits

...

6 commits

Author SHA1 Message Date
James Strong
1ae5d8df20
wip
Signed-off-by: James Strong <james.strong@chainguard.dev>
2023-06-14 09:10:34 -07:00
James Strong
ff3d6bdf97
move release to cobra
Signed-off-by: James Strong <james.strong@chainguard.dev>
2023-06-13 18:02:54 -07:00
James Strong
b3cf60d136
update docker build
Signed-off-by: James Strong <james.strong@chainguard.dev>
2023-06-12 18:28:25 -07:00
James Strong
cbc68bc011
docker build
Signed-off-by: James Strong <strong.james.e@gmail.com>
2023-06-09 16:17:38 -04:00
James Strong
7a32b1abfb
docker build WIP
Signed-off-by: James Strong <james.strong@chainguard.dev>
2023-06-08 22:04:50 -04:00
James Strong
3a8cccc469
testing out moving off bash
Signed-off-by: James Strong <james.strong@chainguard.dev>
2023-06-08 21:49:11 -04:00
12 changed files with 2160 additions and 50 deletions

7
ingressctl/cmd/arch.go Normal file
View file

@ -0,0 +1,7 @@
package cmd
import "runtime"
func getArch() string {
return runtime.GOARCH
}

64
ingressctl/cmd/common.go Normal file
View file

@ -0,0 +1,64 @@
package cmd
import (
"fmt"
"os"
"strings"
"time"
)
var DEBUG bool
func init() {
DEBUG = false
debugENV := os.Getenv("MAGE_DEBUG")
if debugENV == "true" {
DEBUG = true
}
}
// CheckArgs should be used to ensure the right command line arguments are
// passed before executing an example.
func CheckArgs(arg ...string) {
if len(os.Args) < len(arg)+1 {
ErrorF("Usage: %s %s", os.Args[0], strings.Join(arg, " "))
os.Exit(1)
}
}
// CheckIfError should be used to naively panics if an error is not nil.
func CheckIfError(err error, format string, args ...interface{}) {
if err == nil {
return
}
fmt.Printf("\x1b[31;1m%s ERROR %s %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...), err)
os.Exit(1)
}
// Info should be used to describe the example commands that are about to run.
func Info(format string, args ...interface{}) {
fmt.Printf("\x1b[34;1m%s INFO: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...))
}
func timeStamp() string {
t := time.Now()
return t.Format(time.RFC3339)
}
// Warning should be used to display a warning
func Warning(format string, args ...interface{}) {
fmt.Printf("\x1b[36;1m%s WARNING: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...))
}
// Info should be used to describe the example commands that are about to run.
func Debug(format string, args ...interface{}) {
if DEBUG {
fmt.Printf("\x1b[34;1m%s DEBUG: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...))
}
}
// Info should be used to describe the example commands that are about to run.
func ErrorF(format string, args ...interface{}) {
fmt.Printf("\x1b[31;1m%s ERROR: %s\x1b[0m\n", timeStamp(), fmt.Sprintf(format, args...))
}

176
ingressctl/cmd/docker.go Normal file
View file

@ -0,0 +1,176 @@
package cmd
import (
"context"
"fmt"
"os"
"strings"
"github.com/codeskyblue/go-sh"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/spf13/cobra"
)
var dockerCmd = &cobra.Command{
Use: "docker",
Short: "Access to docker client",
}
var dockerListCmd = &cobra.Command{
Use: "list",
Short: "list out all docker images",
Long: "List out all docker images available to us",
Run: func(cmd *cobra.Command, args []string) {
dockerList()
},
}
var dockerBuildCmd = &cobra.Command{
Use: "build",
Long: "build a docker container for use with ingress-nginx",
Run: func(cmd *cobra.Command, args []string) {
dockerBuild()
},
}
var dco dockerBuildOpts
func init() {
rootCmd.AddCommand(dockerCmd)
dockerCmd.AddCommand(dockerListCmd)
dockerCmd.AddCommand(dockerBuildCmd)
dockerBuildCmd.Flags().StringVar(&dco.PlatformFlag, "platformflag", "", "Setting the Docker --platform build flag")
dockerBuildCmd.Flags().StringSliceVar(&dco.Platform, "platforms", PLATFORMS, "comma seperated list of platforms to build for container image")
dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.BaseImage, "base", "", "base image to build container off of")
dockerBuildCmd.Flags().StringVar(&dco.Path, "path", "", "container build path")
dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.Version, "version", "", "docker tag to build")
dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.TargetArch, "targetarch", "", "target arch to build")
dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.CommitSHA, "commitsha", "", "build arg commit sha to add to build")
dockerBuildCmd.Flags().StringVar(&dco.BuildArgs.BuildId, "build-id", "", "build id to add to container metadata")
dockerBuildCmd.Flags().StringVar(&dco.Dockerfile, "dockerfile", "Dockerfile", "dockerfile of image to build")
dockerBuildCmd.Flags().StringVar(&dco.Image.Name, "name", "", "container image name registry/name:tag@digest")
dockerBuildCmd.Flags().StringVar(&dco.Image.Registry, "registry", Registry, "Registry to tag image and push container registry/name:tag@digest")
dockerBuildCmd.Flags().StringVar(&dco.Image.Tag, "tag", "", "container tag registry/name:tag@digest")
dockerBuildCmd.Flags().StringVar(&dco.Image.Digest, "digest", "", "digest of container image registry/name:tag@digest")
}
func dockerList() {
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
panic(err)
}
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
fmt.Printf("%s %s\n", container.ID[:10], container.Image)
}
}
var PLATFORMS = []string{"amd64", "arm", "arm64", "s390x"}
var BUILDX_PLATFORMS = "linux/amd64,linux/arm,linux/arm64,linux/s390x"
var Registry = "gcr.io/k8s-staging-ingress-nginx"
var PKG = "k8s.io/ingress-nginx"
type dockerBuildOpts struct {
PlatformFlag string
Platform []string
BuildArgs BuildArgs
Dockerfile string
Image Image
Path string
}
type BuildArgs struct {
BaseImage string
Version string
TargetArch string
CommitSHA string
BuildId string
}
// ControllerImage - struct with info about controllers
type Image struct {
Tag string
Digest string
Registry string
Name string
}
func (i Image) print() string {
return fmt.Sprintf("%s/%s:%s@sha256:%s", i.Registry, i.Name, i.Tag, i.Digest)
}
func dockerBuild() error {
/*
docker build \
${PLATFORM_FLAG} ${PLATFORM} \
--no-cache \
--pull \
--build-arg BASE_IMAGE="$(BASE_IMAGE)" \
--build-arg VERSION="$(TAG)" \
--build-arg TARGETARCH="$(ARCH)" \
--build-arg COMMIT_SHA="$(COMMIT_SHA)" \
--build-arg BUILD_ID="$(BUILD_ID)" \
-t $(REGISTRY)/controller:$(TAG) rootfs
*/
session := sh.NewSession()
session.ShowCMD = true
fmt.Printf("Container Build Path: %v\n", dco.Path)
buildArgs(&dco.BuildArgs)
fmt.Printf("Base image: %s\n", dco.BuildArgs.BaseImage)
fmt.Printf("Build Args: %s\n", buildArgs)
session.Command("docker", "build", "--no-cache", "--pull",
"--build-arg", "BASE_IMAGE="+dco.BuildArgs.BaseImage,
"--build-arg", "VERSION="+dco.BuildArgs.Version,
"--build-arg", "TARGETARCH="+dco.BuildArgs.TargetArch,
"--build-arg", "COMMIT_SHA="+dco.BuildArgs.CommitSHA,
"--build-arg", "BUILD_ID="+dco.BuildArgs.BuildId,
"-f", dco.Path+dco.Dockerfile,
dco.Path).Run()
return nil
}
func buildArgs(b *BuildArgs) {
if b.BaseImage == "" {
base, err := getIngressNginxBase()
CheckIfError(err, "Issue Retrieving base image")
b.BaseImage = base
}
if b.Version == "" {
b.Version = "1.0.0-dev"
}
if b.TargetArch == "" {
b.TargetArch = getArch()
}
if b.CommitSHA == "" {
sha, _ := sh.Command("git", "rev-parse", "--short", "HEAD").Output()
b.CommitSHA = strings.TrimSpace(string(sha))
}
if b.BuildId == "" {
b.BuildId = "UNSET"
}
}
func getIngressNginxBase() (string, error) {
dat, err := os.ReadFile("../NGINX_BASE")
CheckIfError(err, "Could not read NGINX_BASE file")
datString := string(dat)
//remove newline
datString = strings.Replace(datString, "\n", "", -1)
return datString, nil
}

620
ingressctl/cmd/helm.go Normal file
View file

@ -0,0 +1,620 @@
/*
Copyright 2023 The Kubernetes Authors.
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 cmd
import (
"bytes"
"fmt"
"os"
"strings"
semver "github.com/blang/semver/v4"
"github.com/codeskyblue/go-sh"
"github.com/helm/helm/pkg/chartutil"
yamlpath "github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
"gopkg.in/yaml.v3"
)
const HelmChartPath = "../charts/ingress-nginx/Chart.yaml"
const HelmChartValues = "../charts/ingress-nginx/values.yaml"
// UpdateAppVersion Updates the Helm App Version of Ingress Nginx Controller
func UpdateAppVersion() {
updateAppVersion()
}
func updateAppVersion() {
}
// UpdateVersion Update Helm Version of the Chart
func UpdateVersion(version string) {
updateVersion(version)
}
func currentChartVersion() string {
chart, err := chartutil.LoadChartfile(HelmChartPath)
CheckIfError(err, "HELM Could not Load Chart")
return chart.Version
}
func currentChartAppVersion() string {
chart, err := chartutil.LoadChartfile(HelmChartPath)
CheckIfError(err, "HELM Could not Load Chart")
return chart.AppVersion
}
func updateVersion(version string) {
Info("HELM Reading File %v", HelmChartPath)
chart, err := chartutil.LoadChartfile(HelmChartPath)
CheckIfError(err, "HELM Could not Load Chart")
//Get the current tag
//appVersionV, err := getIngressNGINXVersion()
//CheckIfError(err, "HELM Issue Retrieving the Current Ingress Nginx Version")
//remove the v from TAG
appVersion := version
Info("HELM Ingress-Nginx App Version: %s Chart AppVersion: %s", appVersion, chart.AppVersion)
if appVersion == chart.AppVersion {
Warning("HELM Ingress NGINX Version didnt change Ingress-Nginx App Version: %s Chart AppVersion: %s", appVersion, chart.AppVersion)
return
}
//Update the helm chart
chart.AppVersion = appVersion
cTag, err := semver.Make(chart.Version)
CheckIfError(err, "HELM Creating Chart Version: %v", err)
if err = cTag.IncrementPatch(); err != nil {
ErrorF("HELM Incrementing Chart Version: %v", err)
os.Exit(1)
}
chart.Version = cTag.String()
Debug("HELM Updated Chart Version: %v", chart.Version)
err = chartutil.SaveChartfile(HelmChartPath, chart)
CheckIfError(err, "HELM Saving new Chart")
}
func updateChartReleaseNotes(releasesNotes []string) {
Info("HELM Updating the Chart Release notes")
chart, err := chartutil.LoadChartfile(HelmChartPath)
CheckIfError(err, "HELM Could not Load Chart to update release notes %s", HelmChartPath)
var releaseNoteString string
for i := range releasesNotes {
releaseNoteString = fmt.Sprintf("%s - \"%s\"\n", releaseNoteString, releasesNotes[i])
}
Info("HELM Release note string %s", releaseNoteString)
chart.Annotations["artifacthub.io/changes"] = releaseNoteString
err = chartutil.SaveChartfile(HelmChartPath, chart)
CheckIfError(err, "HELM Saving updated release notes for Chart")
}
func UpdateChartChangelog() {
}
// UpdateChartValue Updates the Helm ChartValue
func UpdateChartValue(key, value string) {
updateChartValue(key, value)
}
func updateChartValue(key, value string) {
Info("HELM Updating Chart %s %s:%s", HelmChartValues, key, value)
//read current values.yaml
data, err := os.ReadFile(HelmChartValues)
CheckIfError(err, "HELM Could not Load Helm Chart Values files %s", HelmChartValues)
//var valuesStruct IngressChartValue
var n yaml.Node
CheckIfError(yaml.Unmarshal(data, &n), "HELM Could not Unmarshal %s", HelmChartValues)
//update value
//keyParse := parsePath(key)
p, err := yamlpath.NewPath(key)
CheckIfError(err, "HELM cannot create path")
q, err := p.Find(&n)
CheckIfError(err, "HELM unexpected error finding path")
for _, i := range q {
Info("HELM Found %s at %s", i.Value, key)
i.Value = value
Info("HELM Updated %s at %s", i.Value, key)
}
// write to file
var b bytes.Buffer
yamlEncoder := yaml.NewEncoder(&b)
yamlEncoder.SetIndent(2)
err = yamlEncoder.Encode(&n)
CheckIfError(err, "HELM Could not Marshal new Values file")
err = os.WriteFile(HelmChartValues, b.Bytes(), 0644)
CheckIfError(err, "HELM Could not write new Values file to %s", HelmChartValues)
Info("HELM Ingress Nginx Helm Chart update %s %s", key, value)
}
func Helmdocs() error {
return runHelmDocs()
}
func runHelmDocs() error {
err := installHelmDocs()
if err != nil {
return err
}
return sh.Command("helm-docs", "--chart-search-root=${PWD}/charts").Run()
}
func installHelmDocs() error {
Info("HELM Install HelmDocs")
return sh.Command("go", "install", "github.com/norwoodj/helm-docs/cmd/helm-docs@v1.11.0").Run()
}
func parsePath(key string) []string {
return strings.Split(key, ".")
}
func updateHelmDocs() {
}
type IngressChartValue struct {
CommonLabels struct {
} `yaml:"commonLabels"`
Controller struct {
Name string `yaml:"name"`
Image struct {
Chroot bool `yaml:"chroot"`
Registry string `yaml:"registry"`
Image string `yaml:"image"`
Tag string `yaml:"tag"`
Digest string `yaml:"digest"`
DigestChroot string `yaml:"digestChroot"`
PullPolicy string `yaml:"pullPolicy"`
RunAsUser int `yaml:"runAsUser"`
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation"`
} `yaml:"image"`
ExistingPsp string `yaml:"existingPsp"`
ContainerName string `yaml:"containerName"`
ContainerPort struct {
HTTP int `yaml:"http"`
HTTPS int `yaml:"https"`
} `yaml:"containerPort"`
Config struct {
} `yaml:"config"`
ConfigAnnotations struct {
} `yaml:"configAnnotations"`
ProxySetHeaders struct {
} `yaml:"proxySetHeaders"`
AddHeaders struct {
} `yaml:"addHeaders"`
DNSConfig struct {
} `yaml:"dnsConfig"`
Hostname struct {
} `yaml:"hostname"`
DNSPolicy string `yaml:"dnsPolicy"`
ReportNodeInternalIP bool `yaml:"reportNodeInternalIp"`
WatchIngressWithoutClass bool `yaml:"watchIngressWithoutClass"`
IngressClassByName bool `yaml:"ingressClassByName"`
AllowSnippetAnnotations bool `yaml:"allowSnippetAnnotations"`
HostNetwork bool `yaml:"hostNetwork"`
HostPort struct {
Enabled bool `yaml:"enabled"`
Ports struct {
HTTP int `yaml:"http"`
HTTPS int `yaml:"https"`
} `yaml:"ports"`
} `yaml:"hostPort"`
ElectionID string `yaml:"electionID"`
IngressClassResource struct {
Name string `yaml:"name"`
Enabled bool `yaml:"enabled"`
Default bool `yaml:"default"`
ControllerValue string `yaml:"controllerValue"`
Parameters struct {
} `yaml:"parameters"`
} `yaml:"ingressClassResource"`
IngressClass string `yaml:"ingressClass"`
PodLabels struct {
} `yaml:"podLabels"`
PodSecurityContext struct {
} `yaml:"podSecurityContext"`
Sysctls struct {
} `yaml:"sysctls"`
PublishService struct {
Enabled bool `yaml:"enabled"`
PathOverride string `yaml:"pathOverride"`
} `yaml:"publishService"`
Scope struct {
Enabled bool `yaml:"enabled"`
Namespace string `yaml:"namespace"`
NamespaceSelector string `yaml:"namespaceSelector"`
} `yaml:"scope"`
ConfigMapNamespace string `yaml:"configMapNamespace"`
TCP struct {
ConfigMapNamespace string `yaml:"configMapNamespace"`
Annotations struct {
} `yaml:"annotations"`
} `yaml:"tcp"`
UDP struct {
ConfigMapNamespace string `yaml:"configMapNamespace"`
Annotations struct {
} `yaml:"annotations"`
} `yaml:"udp"`
MaxmindLicenseKey string `yaml:"maxmindLicenseKey"`
ExtraArgs struct {
} `yaml:"extraArgs"`
ExtraEnvs []interface{} `yaml:"extraEnvs"`
Kind string `yaml:"kind"`
Annotations struct {
} `yaml:"annotations"`
Labels struct {
} `yaml:"labels"`
UpdateStrategy struct {
} `yaml:"updateStrategy"`
MinReadySeconds int `yaml:"minReadySeconds"`
Tolerations []interface{} `yaml:"tolerations"`
Affinity struct {
} `yaml:"affinity"`
TopologySpreadConstraints []interface{} `yaml:"topologySpreadConstraints"`
TerminationGracePeriodSeconds int `yaml:"terminationGracePeriodSeconds"`
NodeSelector struct {
KubernetesIoOs string `yaml:"kubernetes.io/os"`
} `yaml:"nodeSelector"`
LivenessProbe struct {
HTTPGet struct {
Path string `yaml:"path"`
Port int `yaml:"port"`
Scheme string `yaml:"scheme"`
} `yaml:"httpGet"`
InitialDelaySeconds int `yaml:"initialDelaySeconds"`
PeriodSeconds int `yaml:"periodSeconds"`
TimeoutSeconds int `yaml:"timeoutSeconds"`
SuccessThreshold int `yaml:"successThreshold"`
FailureThreshold int `yaml:"failureThreshold"`
} `yaml:"livenessProbe"`
ReadinessProbe struct {
HTTPGet struct {
Path string `yaml:"path"`
Port int `yaml:"port"`
Scheme string `yaml:"scheme"`
} `yaml:"httpGet"`
InitialDelaySeconds int `yaml:"initialDelaySeconds"`
PeriodSeconds int `yaml:"periodSeconds"`
TimeoutSeconds int `yaml:"timeoutSeconds"`
SuccessThreshold int `yaml:"successThreshold"`
FailureThreshold int `yaml:"failureThreshold"`
} `yaml:"readinessProbe"`
HealthCheckPath string `yaml:"healthCheckPath"`
HealthCheckHost string `yaml:"healthCheckHost"`
PodAnnotations struct {
} `yaml:"podAnnotations"`
ReplicaCount int `yaml:"replicaCount"`
MinAvailable int `yaml:"minAvailable"`
Resources struct {
Requests struct {
CPU string `yaml:"cpu"`
Memory string `yaml:"memory"`
} `yaml:"requests"`
} `yaml:"resources"`
Autoscaling struct {
APIVersion string `yaml:"apiVersion"`
Enabled bool `yaml:"enabled"`
Annotations struct {
} `yaml:"annotations"`
MinReplicas int `yaml:"minReplicas"`
MaxReplicas int `yaml:"maxReplicas"`
TargetCPUUtilizationPercentage int `yaml:"targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `yaml:"targetMemoryUtilizationPercentage"`
Behavior struct {
} `yaml:"behavior"`
} `yaml:"autoscaling"`
AutoscalingTemplate []interface{} `yaml:"autoscalingTemplate"`
Keda struct {
APIVersion string `yaml:"apiVersion"`
Enabled bool `yaml:"enabled"`
MinReplicas int `yaml:"minReplicas"`
MaxReplicas int `yaml:"maxReplicas"`
PollingInterval int `yaml:"pollingInterval"`
CooldownPeriod int `yaml:"cooldownPeriod"`
RestoreToOriginalReplicaCount bool `yaml:"restoreToOriginalReplicaCount"`
ScaledObject struct {
Annotations struct {
} `yaml:"annotations"`
} `yaml:"scaledObject"`
Triggers []interface{} `yaml:"triggers"`
Behavior struct {
} `yaml:"behavior"`
} `yaml:"keda"`
EnableMimalloc bool `yaml:"enableMimalloc"`
CustomTemplate struct {
ConfigMapName string `yaml:"configMapName"`
ConfigMapKey string `yaml:"configMapKey"`
} `yaml:"customTemplate"`
Service struct {
Enabled bool `yaml:"enabled"`
AppProtocol bool `yaml:"appProtocol"`
Annotations struct {
} `yaml:"annotations"`
Labels struct {
} `yaml:"labels"`
ExternalIPs []interface{} `yaml:"externalIPs"`
LoadBalancerIP string `yaml:"loadBalancerIP"`
LoadBalancerSourceRanges []interface{} `yaml:"loadBalancerSourceRanges"`
EnableHTTP bool `yaml:"enableHttp"`
EnableHTTPS bool `yaml:"enableHttps"`
IPFamilyPolicy string `yaml:"ipFamilyPolicy"`
IPFamilies []string `yaml:"ipFamilies"`
Ports struct {
HTTP int `yaml:"http"`
HTTPS int `yaml:"https"`
} `yaml:"ports"`
TargetPorts struct {
HTTP string `yaml:"http"`
HTTPS string `yaml:"https"`
} `yaml:"targetPorts"`
Type string `yaml:"type"`
NodePorts struct {
HTTP string `yaml:"http"`
HTTPS string `yaml:"https"`
TCP struct {
} `yaml:"tcp"`
UDP struct {
} `yaml:"udp"`
} `yaml:"nodePorts"`
External struct {
Enabled bool `yaml:"enabled"`
} `yaml:"external"`
Internal struct {
Enabled bool `yaml:"enabled"`
Annotations struct {
} `yaml:"annotations"`
LoadBalancerSourceRanges []interface{} `yaml:"loadBalancerSourceRanges"`
} `yaml:"internal"`
} `yaml:"service"`
ShareProcessNamespace bool `yaml:"shareProcessNamespace"`
ExtraContainers []interface{} `yaml:"extraContainers"`
ExtraVolumeMounts []interface{} `yaml:"extraVolumeMounts"`
ExtraVolumes []interface{} `yaml:"extraVolumes"`
ExtraInitContainers []interface{} `yaml:"extraInitContainers"`
ExtraModules []interface{} `yaml:"extraModules"`
Opentelemetry struct {
Enabled bool `yaml:"enabled"`
Image string `yaml:"image"`
ContainerSecurityContext struct {
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation"`
} `yaml:"containerSecurityContext"`
} `yaml:"opentelemetry"`
AdmissionWebhooks struct {
Annotations struct {
} `yaml:"annotations"`
Enabled bool `yaml:"enabled"`
ExtraEnvs []interface{} `yaml:"extraEnvs"`
FailurePolicy string `yaml:"failurePolicy"`
Port int `yaml:"port"`
Certificate string `yaml:"certificate"`
Key string `yaml:"key"`
NamespaceSelector struct {
} `yaml:"namespaceSelector"`
ObjectSelector struct {
} `yaml:"objectSelector"`
Labels struct {
} `yaml:"labels"`
ExistingPsp string `yaml:"existingPsp"`
NetworkPolicyEnabled bool `yaml:"networkPolicyEnabled"`
Service struct {
Annotations struct {
} `yaml:"annotations"`
ExternalIPs []interface{} `yaml:"externalIPs"`
LoadBalancerSourceRanges []interface{} `yaml:"loadBalancerSourceRanges"`
ServicePort int `yaml:"servicePort"`
Type string `yaml:"type"`
} `yaml:"service"`
CreateSecretJob struct {
SecurityContext struct {
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation"`
} `yaml:"securityContext"`
Resources struct {
} `yaml:"resources"`
} `yaml:"createSecretJob"`
PatchWebhookJob struct {
SecurityContext struct {
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation"`
} `yaml:"securityContext"`
Resources struct {
} `yaml:"resources"`
} `yaml:"patchWebhookJob"`
Patch struct {
Enabled bool `yaml:"enabled"`
Image struct {
Registry string `yaml:"registry"`
Image string `yaml:"image"`
Tag string `yaml:"tag"`
Digest string `yaml:"digest"`
PullPolicy string `yaml:"pullPolicy"`
} `yaml:"image"`
PriorityClassName string `yaml:"priorityClassName"`
PodAnnotations struct {
} `yaml:"podAnnotations"`
NodeSelector struct {
KubernetesIoOs string `yaml:"kubernetes.io/os"`
} `yaml:"nodeSelector"`
Tolerations []interface{} `yaml:"tolerations"`
Labels struct {
} `yaml:"labels"`
SecurityContext struct {
RunAsNonRoot bool `yaml:"runAsNonRoot"`
RunAsUser int `yaml:"runAsUser"`
FsGroup int `yaml:"fsGroup"`
} `yaml:"securityContext"`
} `yaml:"patch"`
CertManager struct {
Enabled bool `yaml:"enabled"`
RootCert struct {
Duration string `yaml:"duration"`
} `yaml:"rootCert"`
AdmissionCert struct {
Duration string `yaml:"duration"`
} `yaml:"admissionCert"`
} `yaml:"certManager"`
} `yaml:"admissionWebhooks"`
Metrics struct {
Port int `yaml:"port"`
PortName string `yaml:"portName"`
Enabled bool `yaml:"enabled"`
Service struct {
Annotations struct {
} `yaml:"annotations"`
ExternalIPs []interface{} `yaml:"externalIPs"`
LoadBalancerSourceRanges []interface{} `yaml:"loadBalancerSourceRanges"`
ServicePort int `yaml:"servicePort"`
Type string `yaml:"type"`
} `yaml:"service"`
ServiceMonitor struct {
Enabled bool `yaml:"enabled"`
AdditionalLabels struct {
} `yaml:"additionalLabels"`
Namespace string `yaml:"namespace"`
NamespaceSelector struct {
} `yaml:"namespaceSelector"`
ScrapeInterval string `yaml:"scrapeInterval"`
TargetLabels []interface{} `yaml:"targetLabels"`
Relabelings []interface{} `yaml:"relabelings"`
MetricRelabelings []interface{} `yaml:"metricRelabelings"`
} `yaml:"serviceMonitor"`
PrometheusRule struct {
Enabled bool `yaml:"enabled"`
AdditionalLabels struct {
} `yaml:"additionalLabels"`
Rules []interface{} `yaml:"rules"`
} `yaml:"prometheusRule"`
} `yaml:"metrics"`
Lifecycle struct {
PreStop struct {
Exec struct {
Command []string `yaml:"command"`
} `yaml:"exec"`
} `yaml:"preStop"`
} `yaml:"lifecycle"`
PriorityClassName string `yaml:"priorityClassName"`
} `yaml:"controller"`
RevisionHistoryLimit int `yaml:"revisionHistoryLimit"`
DefaultBackend struct {
Enabled bool `yaml:"enabled"`
Name string `yaml:"name"`
Image struct {
Registry string `yaml:"registry"`
Image string `yaml:"image"`
Tag string `yaml:"tag"`
PullPolicy string `yaml:"pullPolicy"`
RunAsUser int `yaml:"runAsUser"`
RunAsNonRoot bool `yaml:"runAsNonRoot"`
ReadOnlyRootFilesystem bool `yaml:"readOnlyRootFilesystem"`
AllowPrivilegeEscalation bool `yaml:"allowPrivilegeEscalation"`
} `yaml:"image"`
ExistingPsp string `yaml:"existingPsp"`
ExtraArgs struct {
} `yaml:"extraArgs"`
ServiceAccount struct {
Create bool `yaml:"create"`
Name string `yaml:"name"`
AutomountServiceAccountToken bool `yaml:"automountServiceAccountToken"`
} `yaml:"serviceAccount"`
ExtraEnvs []interface{} `yaml:"extraEnvs"`
Port int `yaml:"port"`
LivenessProbe struct {
FailureThreshold int `yaml:"failureThreshold"`
InitialDelaySeconds int `yaml:"initialDelaySeconds"`
PeriodSeconds int `yaml:"periodSeconds"`
SuccessThreshold int `yaml:"successThreshold"`
TimeoutSeconds int `yaml:"timeoutSeconds"`
} `yaml:"livenessProbe"`
ReadinessProbe struct {
FailureThreshold int `yaml:"failureThreshold"`
InitialDelaySeconds int `yaml:"initialDelaySeconds"`
PeriodSeconds int `yaml:"periodSeconds"`
SuccessThreshold int `yaml:"successThreshold"`
TimeoutSeconds int `yaml:"timeoutSeconds"`
} `yaml:"readinessProbe"`
Tolerations []interface{} `yaml:"tolerations"`
Affinity struct {
} `yaml:"affinity"`
PodSecurityContext struct {
} `yaml:"podSecurityContext"`
ContainerSecurityContext struct {
} `yaml:"containerSecurityContext"`
PodLabels struct {
} `yaml:"podLabels"`
NodeSelector struct {
KubernetesIoOs string `yaml:"kubernetes.io/os"`
} `yaml:"nodeSelector"`
PodAnnotations struct {
} `yaml:"podAnnotations"`
ReplicaCount int `yaml:"replicaCount"`
MinAvailable int `yaml:"minAvailable"`
Resources struct {
} `yaml:"resources"`
ExtraVolumeMounts []interface{} `yaml:"extraVolumeMounts"`
ExtraVolumes []interface{} `yaml:"extraVolumes"`
Autoscaling struct {
Annotations struct {
} `yaml:"annotations"`
Enabled bool `yaml:"enabled"`
MinReplicas int `yaml:"minReplicas"`
MaxReplicas int `yaml:"maxReplicas"`
TargetCPUUtilizationPercentage int `yaml:"targetCPUUtilizationPercentage"`
TargetMemoryUtilizationPercentage int `yaml:"targetMemoryUtilizationPercentage"`
} `yaml:"autoscaling"`
Service struct {
Annotations struct {
} `yaml:"annotations"`
ExternalIPs []interface{} `yaml:"externalIPs"`
LoadBalancerSourceRanges []interface{} `yaml:"loadBalancerSourceRanges"`
ServicePort int `yaml:"servicePort"`
Type string `yaml:"type"`
} `yaml:"service"`
PriorityClassName string `yaml:"priorityClassName"`
Labels struct {
} `yaml:"labels"`
} `yaml:"defaultBackend"`
Rbac struct {
Create bool `yaml:"create"`
Scope bool `yaml:"scope"`
} `yaml:"rbac"`
PodSecurityPolicy struct {
Enabled bool `yaml:"enabled"`
} `yaml:"podSecurityPolicy"`
ServiceAccount struct {
Create bool `yaml:"create"`
Name string `yaml:"name"`
AutomountServiceAccountToken bool `yaml:"automountServiceAccountToken"`
Annotations struct {
} `yaml:"annotations"`
} `yaml:"serviceAccount"`
ImagePullSecrets []interface{} `yaml:"imagePullSecrets"`
TCP struct {
} `yaml:"tcp"`
UDP struct {
} `yaml:"udp"`
PortNamePrefix string `yaml:"portNamePrefix"`
DhParam interface{} `yaml:"dhParam"`
}

574
ingressctl/cmd/release.go Normal file
View file

@ -0,0 +1,574 @@
/*
Copyright 2023 The Kubernetes Authors.
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 cmd
import (
"context"
"errors"
"fmt"
"io"
"net"
"net/http"
"os"
"text/template"
"github.com/codeskyblue/go-sh"
"github.com/google/go-github/v48/github"
"github.com/spf13/cobra"
"golang.org/x/oauth2"
"gopkg.in/yaml.v3"
"regexp"
"strings"
"time"
)
// var INGRESS_ORG = "kubernetes" // the owner so we can test from forks
var INGRESS_ORG = "strongjz" // the owner so we can test from forks
var INGRESS_REPO = "ingress-nginx" // the repo to pull from
var RELEASE_BRANCH = "main" //we only release from main
var GITHUB_TOKEN string // the Google/gogithub lib needs an PAT to access the GitHub API
// var K8S_IO_ORG = "kubernetes" //the owner or organization for the k8s.io repo
var K8S_IO_ORG = "strongjz" //the owner or organization for the k8s.io repo
var K8S_IO_REPO = "k8s.io" //the repo that holds the images yaml for production promotion
var INGRESS_REGISTRY = "registry.k8s.io" //Container registry for storage Ingress-nginx images
var KUSTOMIZE_INSTALL_VERSION = "sigs.k8s.io/kustomize/kustomize/v4@v4.5.4" //static deploys needs kustomize to generate the template
// ingress-nginx releases start with a TAG then a cloudbuild, then a promotion through a PR, this the location of that PR
var IMAGES_YAML = "https://raw.githubusercontent.com/strongjz/k8s.io/main/registry.k8s.io/images/k8s-staging-ingress-nginx/images.yaml"
var ctx = context.Background() // Context used for GitHub Client
const INDEX_DOCS = "docs/deploy/index.md" //index.md has a version of the controller and needs to updated
const CHANGELOG = "Changelog.md" //Name of the changelog
var releaseCmd = &cobra.Command{
Use: "release",
Short: "Start a release",
Long: "Start a new release for ingress-nginx",
Run: func(cmd *cobra.Command, args []string) {
},
}
var helmReleaseCmd = &cobra.Command{
Use: "helm",
Short: "Start a new helm chart release",
Long: "Start a new helm chart release",
Run: func(cmd *cobra.Command, args []string) {
},
}
var controllerReleaseCmd = &cobra.Command{
Use: "controller",
Short: "Release Ingress-nginx Controller",
Long: "Release a new version of ingress-nginx controller",
Run: func(cmd *cobra.Command, args []string) {
},
}
func init() {
rootCmd.AddCommand(releaseCmd)
releaseCmd.AddCommand(helmReleaseCmd)
releaseCmd.AddCommand(controllerReleaseCmd)
}
// ControllerImage - struct with info about controllers
type ControllerImage struct {
Tag string
Digest string
Registry string
Name string
}
// IngressRelease All the information about an ingress-nginx release that gets updated
type IngressRelease struct {
ControllerVersion string
ControllerImage ControllerImage
ReleaseNote ReleaseNote
Release *github.RepositoryRelease
}
// ReleaseNote - All the pieces of information/documents that get updated during a release
type ReleaseNote struct {
Version string
NewControllerVersion string
PreviousControllerVersion string
ControllerImages []ControllerImage
DepUpdates []string
Updates []string
HelmUpdates []string
NewHelmChartVersion string
PreviousHelmChartVersion string
}
// IMAGES_YAML returns this data structure
type ImageYamls []ImageElement
// ImageElement - a specific image and it's data structure the dmap is a list of shas and container versions
type ImageElement struct {
Name string `json:"name"`
Dmap map[string][]string `json:"dmap"`
}
// init will set the GitHub token from the committers/releasers env var
func init() {
GITHUB_TOKEN = os.Getenv("GITHUB_TOKEN")
}
// PromoteImage Creates PR into the k8s.io repo for promotion of ingress from staging to production
func PromoteImage(version, sha string) {
}
// Release Create a new release of ingress nginx controller
func NewRelease(version string) {
//newRelease := Release{}
//update ingress-nginx version
//This is the step that kicks all the release process
//it is already done, so it kicks off the gcloud build of the controller images
//mg.Deps(mg.F(Tag.BumpNginx, version))
tag, err := getIngressNGINXVersion()
CheckIfError(err, "RELEASE Retrieving the current Ingress Nginx Version")
Info("RELEASE Checking Current Version %s to New Version %s", tag, version)
//if the version were upgrading does not match the TAG file, lets update the TAG file
if tag[1:] != version {
Warning("RELEASE Ingress Nginx TAG %s and new version %s do not match", tag, version)
BumpNginx(fmt.Sprintf("v%s", version))
}
//update git controller tag controller-v$version
NewControllerTag(version)
//make release notes
releaseNotes, err := makeReleaseNotes(version)
CheckIfError(err, "RELEASE Creating Release Notes for version %s", version)
Info("RELEASE Release Notes %s completed", releaseNotes.Version)
//update chart values.yaml new controller tag and image digest
releaseNotes.PreviousHelmChartVersion = currentChartVersion()
//controller tag
updateChartValue("controller.image.tag", fmt.Sprintf("v%s", releaseNotes.Version))
Debug("releaseNotes.ControllerImages[0].Name %s", releaseNotes.ControllerImages[0].Name)
Debug("releaseNotes.ControllerImages[1].Name %s", releaseNotes.ControllerImages[1].Name)
//controller digest
if releaseNotes.ControllerImages[0].Name == "ingress-nginx/controller" {
Debug("Updating Chart Value %s with %s", "controller.image.digest", releaseNotes.ControllerImages[0].Digest)
updateChartValue("controller.image.digest", releaseNotes.ControllerImages[0].Digest)
}
//controller chroot digest
if releaseNotes.ControllerImages[1].Name == "ingress-nginx/controller-chroot" {
Debug("Updating Chart Value %s with %s", "controller.image.digestChroot", releaseNotes.ControllerImages[1].Digest)
updateChartValue("controller.image.digestChroot", releaseNotes.ControllerImages[1].Digest)
}
//update helm chart app version
//mg.Deps(mg.F(Helm.UpdateVersion, version))
releaseNotes.NewHelmChartVersion = currentChartVersion()
//update helm chart release notes
updateChartReleaseNotes(releaseNotes.HelmUpdates)
//Run helm docs update
CheckIfError(runHelmDocs(), "Error Updating Helm Docs ")
releaseNotes.helmTemplate()
//update static manifest
CheckIfError(updateStaticManifest(), "Error Updating Static manifests")
//update e2e docs
updateE2EDocs()
//update documentation with ingress-nginx version
CheckIfError(updateIndexMD(releaseNotes.PreviousControllerVersion, releaseNotes.NewControllerVersion), "Error Updating %s", INDEX_DOCS)
//keeping these manual for now
//git commit TODO
//make Pull Request TODO
//make release TODO
//mg.Deps(mg.F(Release.CreateRelease, version))
}
// the index.md doc needs the controller version updated
func updateIndexMD(old, new string) error {
Info("Updating Deploy docs with new version")
data, err := os.ReadFile(INDEX_DOCS)
CheckIfError(err, "Could not read INDEX_DOCS file %s", INDEX_DOCS)
datString := string(data)
datString = strings.Replace(datString, old, new, -1)
err = os.WriteFile(INDEX_DOCS, []byte(datString), 644)
if err != nil {
ErrorF("Could not write new %s %s", INDEX_DOCS, err)
return err
}
return nil
}
// runs the hack/generate-deploy-scripts.sh
func updateE2EDocs() {
updates, err := sh.Command("./hack/generate-e2e-suite-doc.sh").Output()
CheckIfError(err, "Could not run update hack script")
err = os.WriteFile("docs/e2e-tests.md", []byte(updates), 644)
CheckIfError(err, "Could not write new e2e test file ")
}
// The static deploy scripts use kustomize to generate them, this function ensures kustomize is installed
func installKustomize() error {
Info("Install Kustomize")
return sh.Command("go", "install", KUSTOMIZE_INSTALL_VERSION).Run()
}
func updateStaticManifest() error {
CheckIfError(installKustomize(), "error installing kustomize")
//hack/generate-deploy-scripts.sh
return sh.Command("./hack/generate-deploy-scripts.sh").Run()
}
//// CreateRelease Creates a new GitHub Release
//func (Release) CreateRelease(name string) {
// releaser, err := gh_release.NewReleaser(INGRESS_ORG, INGRESS_REPO, GITHUB_TOKEN)
// CheckIfError(err, "GitHub Release Client error")
// newRelease, err := releaser.Create(fmt.Sprintf("controller-%s", name))
// CheckIfError(err, "Create release error")
// Info("New Release: Tag %v, ID: %v", newRelease.TagName, newRelease.ID)
//}
// Returns a GitHub client ready for use
func githubClient() *github.Client {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: GITHUB_TOKEN},
)
oauthClient := oauth2.NewClient(ctx, ts)
return github.NewClient(oauthClient)
}
// LatestCommitLogs Retrieves the commit log between the latest two controller versions.
func LatestCommitLogs() {
commitLog := commitsBetweenTags()
for i, s := range commitLog {
Info("#%v Version %v", i, s)
}
}
func commitsBetweenTags() []string {
tags := getAllControllerTags()
Info("Getting Commits between %v and %v", tags[0], tags[1])
commitLog, err := sh.Command("git", "log", "--full-history", "--pretty", "--oneline", fmt.Sprintf("%v..%v", tags[1], tags[0])).Output()
if len(commitLog) == 0 {
Warning("All Controller Tags is empty")
}
CheckIfError(err, "Retrieving Commit log")
return strings.Split(string(commitLog), "\n")
}
// Generate Release Notes
func ReleaseNotes(newVersion string) error {
notes, err := makeReleaseNotes(newVersion)
CheckIfError(err, "Creating Release Notes for version %s", newVersion)
Info("Release Notes %s completed", notes.Version)
return nil
}
func makeReleaseNotes(newVersion string) (*ReleaseNote, error) {
var newReleaseNotes = ReleaseNote{}
newReleaseNotes.Version = newVersion
allControllerTags := getAllControllerTags()
//new version
newReleaseNotes.NewControllerVersion = allControllerTags[0]
newControllerVersion := fmt.Sprintf("controller-v%s", newVersion)
//the newControllerVersion should match the latest tag
if newControllerVersion != allControllerTags[0] {
return nil, errors.New(fmt.Sprintf("Generating release new version %s didnt match the current latest tag %s", newControllerVersion, allControllerTags[0]))
}
//previous version
newReleaseNotes.PreviousControllerVersion = allControllerTags[1]
Info("New Version: %s Old Version: %s", newReleaseNotes.NewControllerVersion, newReleaseNotes.PreviousControllerVersion)
commits := commitsBetweenTags()
//dependency_updates
//all_updates
var allUpdates []string
var depUpdates []string
var helmUpdates []string
prRegex := regexp.MustCompile("\\(#\\d+\\)")
depBot := regexp.MustCompile("^(\\w){1,10} Bump ")
helmRegex := regexp.MustCompile("helm|chart")
for i, s := range commits {
//matches on PR
if prRegex.Match([]byte(s)) {
//matches a dependant bot update
if depBot.Match([]byte(s)) { //
Debug("#%v DEPENDABOT %v", i, s)
u := strings.SplitN(s, " ", 2)
depUpdates = append(depUpdates, u[1])
} else { // add it to the all updates slice
Debug("#%v ALL UPDATES %v", i, s)
u := strings.SplitN(s, " ", 2)
allUpdates = append(allUpdates, u[1])
//helm chart updates
if helmRegex.Match([]byte(s)) {
u := strings.SplitN(s, " ", 2)
helmUpdates = append(helmUpdates, u[1])
}
}
}
}
helmUpdates = append(helmUpdates, fmt.Sprintf("Update Ingress-Nginx version %s", newReleaseNotes.NewControllerVersion))
newReleaseNotes.Updates = allUpdates
newReleaseNotes.DepUpdates = depUpdates
newReleaseNotes.HelmUpdates = helmUpdates
//controller_image_digests
imagesYaml, err := downloadFile(IMAGES_YAML)
if err != nil {
ErrorF("Could not download file %s : %s", IMAGES_YAML, err)
return nil, err
}
Debug("%s", imagesYaml)
data := ImageYamls{}
err = yaml.Unmarshal([]byte(imagesYaml), &data)
if err != nil {
ErrorF("Could not unmarshal images yaml %s", err)
return nil, err
}
//controller
controllerDigest := findImageDigest(data, "controller", newVersion)
if len(controllerDigest) == 0 {
ErrorF("Controller Digest could not be found")
return nil, errors.New("Controller digest could not be found")
}
controllerChrootDigest := findImageDigest(data, "controller-chroot", newVersion)
if len(controllerChrootDigest) == 0 {
ErrorF("Controller Chroot Digest could not be found")
return nil, errors.New("Controller Chroot digest could not be found")
}
Debug("Latest Controller Digest %v", controllerDigest)
Debug("Latest Controller Chroot Digest %v", controllerChrootDigest)
c1 := ControllerImage{
Digest: controllerDigest,
Registry: INGRESS_REGISTRY,
Name: "ingress-nginx/controller",
Tag: fmt.Sprintf("v%s", newReleaseNotes.Version),
}
c2 := ControllerImage{
Digest: controllerChrootDigest,
Registry: INGRESS_REGISTRY,
Name: "ingress-nginx/controller-chroot",
Tag: fmt.Sprintf("v%s", newReleaseNotes.Version),
}
newReleaseNotes.ControllerImages = append(newReleaseNotes.ControllerImages, c1)
newReleaseNotes.ControllerImages = append(newReleaseNotes.ControllerImages, c2)
Debug("New Release Controller Images %s %s", newReleaseNotes.ControllerImages[0].Digest, newReleaseNotes.ControllerImages[1].Digest)
if DEBUG {
newReleaseNotes.printRelease()
}
//write it all out to the changelog file
newReleaseNotes.template()
return &newReleaseNotes, nil
}
func (i ControllerImage) print() string {
return fmt.Sprintf("%s/%s:%s@%s", i.Registry, i.Name, i.Tag, i.Digest)
}
func (r ReleaseNote) template() {
// Files are provided as a slice of strings.
changelogTemplate, err := os.ReadFile("Changelog.md.gotmpl")
if err != nil {
ErrorF("Could not read changelog template file %s", err)
}
Debug("ChangeLog Templates %s", string(changelogTemplate))
t := template.Must(template.New("changelog").Parse(string(changelogTemplate)))
// create a new file
file, err := os.Create(fmt.Sprintf("changelog/Changelog-%s.md", r.Version))
if err != nil {
ErrorF("Could not create changelog file %s", err)
}
defer file.Close()
err = t.Execute(file, r)
if err != nil {
ErrorF("executing template:", err)
}
}
func (r ReleaseNote) helmTemplate() {
// Files are provided as a slice of strings.
changelogTemplate, err := os.ReadFile("charts/ingress-nginx/changelog.md.gotmpl")
if err != nil {
ErrorF("Could not read changelog template file %s", err)
}
Debug("ChangeLog Templates %s", string(changelogTemplate))
t := template.Must(template.New("changelog").Parse(string(changelogTemplate)))
// create a new file
file, err := os.Create(fmt.Sprintf("charts/ingress-nginx/changelog/Changelog-%s.md", r.NewHelmChartVersion))
if err != nil {
ErrorF("Could not create changelog file %s", err)
}
defer file.Close()
err = t.Execute(file, r)
if err != nil {
ErrorF("executing template:", err)
}
}
func (r ReleaseNote) printRelease() {
Info("Release Version: %v", r.NewControllerVersion)
Info("Previous Version: %v", r.PreviousControllerVersion)
Info("Controller Image: %v", r.ControllerImages[0].print())
Info("Controller Chroot Image: %v", r.ControllerImages[1].print())
for i := range r.Updates {
Info("Update #%v - %v", i, r.Updates[i])
}
for j := range r.DepUpdates {
Info("Dependabot Update #%v - %v", j, r.DepUpdates[j])
}
}
func findImageDigest(yaml ImageYamls, image, version string) string {
version = fmt.Sprintf("v%s", version)
Info("Searching Digest for %s:%s", image, version)
for i := range yaml {
if yaml[i].Name == image {
for k, v := range yaml[i].Dmap {
if v[0] == version {
return k
}
}
return ""
}
}
return ""
}
func downloadFile(url string) (string, error) {
client := &http.Client{
Transport: &http.Transport{
DialContext: (&net.Dialer{
Timeout: 5 * time.Second,
KeepAlive: 5 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 5 * time.Second,
ResponseHeaderTimeout: 5 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConnsPerHost: -1,
},
}
resp, err := client.Get(url)
if err != nil {
return "", nil
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", errors.New(fmt.Sprintf("Could not retrieve file, response from server %s for file %s", resp.StatusCode, url))
}
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
return "", nil
}
return string(bodyBytes), nil
}
// Latest returns latest Github Release
func ReleaseLatest() error {
r, _, err := latestRelease()
if err != nil {
ErrorF("Latest Release error %s", err)
return err
}
Info("Latest Release %v", r.String())
return nil
}
func ReleaseByTag(tag string) error {
r, _, err := releaseByTag(tag)
if err != nil {
ErrorF("Release retrieve tag error %s", tag, err)
return err
}
Info("Latest Release %v", r.String())
return nil
}
func releaseByTag(tag string) (*github.RepositoryRelease, *github.Response, error) {
ghClient := githubClient()
return ghClient.Repositories.GetReleaseByTag(ctx, INGRESS_ORG, INGRESS_REPO, tag)
}
func latestRelease() (*github.RepositoryRelease, *github.Response, error) {
ghClient := githubClient()
return ghClient.Repositories.GetLatestRelease(ctx, INGRESS_ORG, INGRESS_REPO)
}
// Copy Test function to copy a release
func ReleaseCopy() error {
ghClient := githubClient()
kRelease, _, err := ghClient.Repositories.GetLatestRelease(ctx, "kubernetes", "ingress-nginx")
if err != nil {
ErrorF("Get Release from kubernetes %s", err)
return err
}
sRelease := &github.RepositoryRelease{
TagName: kRelease.TagName,
Name: kRelease.Name,
Body: kRelease.Body,
Draft: kRelease.Draft,
Prerelease: kRelease.GenerateReleaseNotes,
DiscussionCategoryName: kRelease.DiscussionCategoryName,
GenerateReleaseNotes: kRelease.GenerateReleaseNotes,
}
sRelease, _, err = ghClient.Repositories.CreateRelease(ctx, "strongjz", "ingress-nginx", sRelease)
if err != nil {
ErrorF("Creating Strongjz release %s", err)
return err
}
Info("Copied over Kubernetes Release %v to Strongjz %v", &kRelease.Name, &sRelease.Name)
return nil
}

66
ingressctl/cmd/root.go Normal file
View file

@ -0,0 +1,66 @@
package cmd
import (
"fmt"
"io"
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "ingressctl",
Short: "CLI",
Long: `CLI for managing ingress-nginx repo`,
}
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func init() {
rootCmd.AddCommand(newCmdCompletion(os.Stdout))
rootCmd.SetOut(os.Stdout)
rootCmd.SetErr(os.Stderr)
}
const completionExample = `
# Installing bash completion on macOS using homebrew
## If running Bash 3.2 included with macOS
brew install bash-completion
## or, if running Bash 4.1+
brew install bash-completion@2
`
func newCmdCompletion(out io.Writer) *cobra.Command {
cmd := &cobra.Command{
Use: "completion [shell]",
Short: "Output shell completion code",
Long: ``,
Example: completionExample,
RunE: func(cmd *cobra.Command, args []string) error {
return runCompletion(out, cmd, args)
},
ValidArgs: []string{"bash", "zsh", "fish"},
}
return cmd
}
func runCompletion(out io.Writer, cmd *cobra.Command, args []string) error {
if len(args) > 1 {
return fmt.Errorf("too many arguments; expected only the shell type: %s", args)
}
if len(args) == 0 || args[0] == "bash" {
return cmd.Root().GenBashCompletion(out)
} else if args[0] == "zsh" {
return cmd.Root().GenZshCompletion(out)
} else if args[0] == "fish" {
return cmd.Root().GenFishCompletion(out, true)
}
return fmt.Errorf("unsupported shell: %s", args[0])
}

160
ingressctl/cmd/tags.go Normal file
View file

@ -0,0 +1,160 @@
/*
Copyright 2023 The Kubernetes Authors.
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 cmd
import (
"fmt"
"os"
"strings"
"github.com/codeskyblue/go-sh"
semver "github.com/blang/semver/v4"
"github.com/spf13/cobra"
)
var tagCmd = &cobra.Command{
Use: "tag",
Short: "taggin information",
Long: "Retieves tagging information about the controller",
}
var ingressVersionCmd = &cobra.Command{
Use: "controller",
Short: "Ingress-Nginx controller version",
Run: func(cmd *cobra.Command, args []string) {
vers, err := getIngressNGINXVersion()
if err != nil {
ErrorF("Could not determine ingress-nginx version: %v", err)
}
Info("Current Ingress-nginx version: %s", vers)
},
}
func init() {
rootCmd.AddCommand(tagCmd)
tagCmd.AddCommand(ingressVersionCmd)
}
func getIngressNGINXVersion() (string, error) {
dat, err := os.ReadFile("../TAG")
CheckIfError(err, "Could not read TAG file")
datString := string(dat)
//remove newline
datString = strings.Replace(datString, "\n", "", -1)
return datString, nil
}
func checkSemVer(currentVersion, newVersion string) bool {
Info("Checking Sem Ver between current %s and new %s", currentVersion, newVersion)
cVersion, err := semver.Make(currentVersion[1:])
if err != nil {
ErrorF("TAG Error Current Tag %v Making Semver : %v", currentVersion[1:], err)
return false
}
nVersion, err := semver.Make(newVersion)
if err != nil {
ErrorF("TAG %v Error Making Semver %v \n", newVersion, err)
return false
}
err = nVersion.Validate()
if err != nil {
ErrorF("TAG %v not a valid Semver %v \n", newVersion, err)
return false
}
//The result will be
//0 if newVersion == currentVersion
//-1 if newVersion < currentVersion
//+1 if newVersion > currentVersion.
Info("TAG Comparing Old %s to New %s", cVersion.String(), nVersion.String())
comp := nVersion.Compare(cVersion)
if comp <= 0 {
Warning("SemVer:%v is not an update\n", newVersion)
return false
}
return true
}
// BumpNginx will update the nginx TAG
func BumpNginx(newTag string) {
Info("TAG BumpNginx version %v", newTag)
currentTag, err := getIngressNGINXVersion()
CheckIfError(err, "Getting Ingress-nginx Version")
bump(currentTag, newTag)
}
func bump(currentTag, newTag string) {
//check if semver is valid
if !checkSemVer(currentTag, newTag) {
ErrorF("ERROR: Semver is not valid %v", newTag)
os.Exit(1)
}
Info("Updating Tag %v to %v", currentTag, newTag)
err := os.WriteFile("../TAG", []byte(newTag), 0666)
CheckIfError(err, "Error Writing New Tag File")
}
// Git Returns the latest git tag
func Git() {
tag, err := getGitTag()
CheckIfError(err, "Retrieving Git Tag")
Info("Git tag: %v", tag)
}
func getGitTag() (string, error) {
out, err := sh.Command("git", "describe", "--tags", "--match", "controller-v*", "--abbrev=1").Output()
return string(out), err
}
// ControllerTag Creates a new Git Tag for the ingress controller
func NewControllerTag(version string) {
Info("Create Ingress Nginx Controller Tag v%s", version)
tag, err := controllerTag(version)
CheckIfError(err, "Creating git tag")
Debug("Git Tag: %s", tag)
}
func controllerTag(version string) (string, error) {
out, err := sh.Command("git", "tag", "-a", "-m", fmt.Sprintf("-m \"Automated Controller release %v\"", version), fmt.Sprintf("controller-v%s", version)).Output()
return string(out), err
}
func AllControllerTags() {
tags := getAllControllerTags()
for i, s := range tags {
Info("#%v Version %v", i, s)
}
}
func getAllControllerTags() []string {
out, err := sh.Command("git", "tag", "-l", "--sort=-v:refname", "controller-v*").Output()
CheckIfError(err, "Retrieving git tags")
if err != nil {
Warning("Issue Running Command")
}
if len(out) == 0 {
Warning("All Controller Tags is empty")
}
Debug("Controller Tags: %v", out)
temp := strings.Split(string(out), "\n")
Debug("There are %v controller tags", len(temp))
return temp
}

111
ingressctl/go.mod Normal file
View file

@ -0,0 +1,111 @@
module github.com/kubernetes/ingress-nginx/ingressctl
go 1.20
require (
github.com/blang/semver/v4 v4.0.0
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe
github.com/docker/docker v24.0.2+incompatible
github.com/google/go-github/v48 v48.2.0
github.com/helm/helm v2.17.0+incompatible
github.com/spf13/cobra v1.7.0
github.com/vmware-labs/yaml-jsonpath v0.3.2
golang.org/x/oauth2 v0.9.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/kubectl v0.27.2
)
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/chai2010/gettext-go v1.0.2 // indirect
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/daviddengcn/go-colortext v1.0.0 // indirect
github.com/docker/distribution v2.8.2+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/fatih/camelcase v1.0.0 // indirect
github.com/fvbommel/sortorder v1.0.1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/imdario/mergo v0.3.6 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lithammer/dedent v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.4 // indirect
github.com/xlab/treeprint v1.1.0 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.11.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.4.0 // indirect
k8s.io/api v0.27.2 // indirect
k8s.io/apimachinery v0.27.2 // indirect
k8s.io/cli-runtime v0.27.2 // indirect
k8s.io/client-go v0.27.2 // indirect
k8s.io/component-base v0.27.2 // indirect
k8s.io/component-helpers v0.27.2 // indirect
k8s.io/helm v2.17.0+incompatible // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/metrics v0.27.2 // indirect
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/kustomize/api v0.13.2 // indirect
sigs.k8s.io/kustomize/kustomize/v5 v5.0.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

374
ingressctl/go.sum Normal file
View file

@ -0,0 +1,374 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe h1:69JI97HlzP+PH5Mi1thcGlDoBr6PS2Oe+l3mNmAkbs4=
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v1.0.0 h1:ANqDyC0ys6qCSvuEK7l3g5RaehL/Xck9EX8ATG8oKsE=
github.com/daviddengcn/go-colortext v1.0.0/go.mod h1:zDqEI5NVUop5QPpVJUxE9UO10hRnmkD5G4Pmri9+m4c=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg=
github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 h1:aRd8M7HJVZOqn/vhOzrGcQH0lNAMkqMn+pXUYkatmcA=
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960/go.mod h1:9HQzr9D/0PGwMEbC3d5AB7oi67+h4TsQqItC1GVYG58=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fvbommel/sortorder v1.0.1 h1:dSnXLt4mJYH25uDDGa3biZNQsozaUWDSWeKJ0qqFfzE=
github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.1 h1:FBLnyygC4/IZZr893oiomc9XaghoveYTrLC1F86HID8=
github.com/go-openapi/jsonreference v0.20.1/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
github.com/golangplus/bytes v1.0.0/go.mod h1:AdRaCFwmc/00ZzELMWb01soso6W1R/++O1XL80yAn+A=
github.com/golangplus/fmt v1.0.0/go.mod h1:zpM0OfbMCjPtd2qkTD/jX2MgiFCqklhSUFyDW44gVQE=
github.com/golangplus/testing v1.0.0 h1:+ZeeiKZENNOMkTTELoSySazi+XaEhVO0mb+eanrSEUQ=
github.com/golangplus/testing v1.0.0/go.mod h1:ZDreixUV3YzhoVraIDyOzHrr76p6NUh6k/pPg/Q3gYA=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v48 v48.2.0 h1:68puzySE6WqUY9KWmpOsDEQfDZsso98rT6pZcz9HqcE=
github.com/google/go-github/v48 v48.2.0/go.mod h1:dDlehKBDo850ZPvCTK0sEqTCVWcrGl2LcDiajkYi89Y=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/helm/helm v2.17.0+incompatible h1:0iy95yMXrfWpwaoOA9XRP+cTvitTrq+LcJV9DvR5n1Y=
github.com/helm/helm v2.17.0+incompatible/go.mod h1:ahXhuvluW4YnSL6W6hDVetZsVK8Pv4BP8OwKli7aMqo=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.2 h1:uqH7bpe+ERSiDa34FDOF7RikN6RzXgduUF8yarlZp94=
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.27.4 h1:Z2AnStgsdSayCMDiCU42qIz+HLqEPcgiOCXjAU/w+8E=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/vmware-labs/yaml-jsonpath v0.3.2 h1:/5QKeCBGdsInyDCyVNLbXyilb61MXGi9NP674f9Hobk=
github.com/vmware-labs/yaml-jsonpath v0.3.2/go.mod h1:U6whw1z03QyqgWdgXxvVnQ90zN1BWz5V+51Ewf8k+rQ=
github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20191026110619-0b21df46bc1d/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.27.2 h1:+H17AJpUMvl+clT+BPnKf0E3ksMAzoBBg7CntpSuADo=
k8s.io/api v0.27.2/go.mod h1:ENmbocXfBT2ADujUXcBhHV55RIT31IIEvkntP6vZKS4=
k8s.io/apimachinery v0.27.2 h1:vBjGaKKieaIreI+oQwELalVG4d8f3YAMNpWLzDXkxeg=
k8s.io/apimachinery v0.27.2/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
k8s.io/cli-runtime v0.27.2 h1:9HI8gfReNujKXt16tGOAnb8b4NZ5E+e0mQQHKhFGwYw=
k8s.io/cli-runtime v0.27.2/go.mod h1:9UecpyPDTkhiYY4d9htzRqN+rKomJgyb4wi0OfrmCjw=
k8s.io/client-go v0.27.2 h1:vDLSeuYvCHKeoQRhCXjxXO45nHVv2Ip4Fe0MfioMrhE=
k8s.io/client-go v0.27.2/go.mod h1:tY0gVmUsHrAmjzHX9zs7eCjxcBsf8IiNe7KQ52biTcQ=
k8s.io/component-base v0.27.2 h1:neju+7s/r5O4x4/txeUONNTS9r1HsPbyoPBAtHsDCpo=
k8s.io/component-base v0.27.2/go.mod h1:5UPk7EjfgrfgRIuDBFtsEFAe4DAvP3U+M8RTzoSJkpo=
k8s.io/component-helpers v0.27.2 h1:i9TgWJ6TH8lQ9x4ExHOwhVitrRpBOr7Wn8aZLbBWxkc=
k8s.io/component-helpers v0.27.2/go.mod h1:NwcpSKo1xzXtUtrUjj5NTSVWex84UPua/z0PYDcCzNo=
k8s.io/helm v2.17.0+incompatible h1:Bpn6o1wKLYqKM3+Osh8e+1/K2g/GsQJ4F4yNF2+deao=
k8s.io/helm v2.17.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI=
k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
k8s.io/kubectl v0.27.2 h1:sSBM2j94MHBFRWfHIWtEXWCicViQzZsb177rNsKBhZg=
k8s.io/kubectl v0.27.2/go.mod h1:GCOODtxPcrjh+EC611MqREkU8RjYBh10ldQCQ6zpFKw=
k8s.io/metrics v0.27.2 h1:TD6z3dhhN9bgg5YkbTh72bPiC1BsxipBLPBWyC3VQAU=
k8s.io/metrics v0.27.2/go.mod h1:v3OT7U0DBvoAzWVzGZWQhdV4qsRJWchzs/LeVN8bhW4=
k8s.io/utils v0.0.0-20230209194617-a36077c30491 h1:r0BAOLElQnnFhE/ApUsg3iHdVYYPBjNSSOMowRZxxsY=
k8s.io/utils v0.0.0-20230209194617-a36077c30491/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kustomize/api v0.13.2 h1:kejWfLeJhUsTGioDoFNJET5LQe/ajzXhJGYoU+pJsiA=
sigs.k8s.io/kustomize/api v0.13.2/go.mod h1:DUp325VVMFVcQSq+ZxyDisA8wtldwHxLZbr1g94UHsw=
sigs.k8s.io/kustomize/kustomize/v5 v5.0.1 h1:HWXbyKDNwGqol+s/sMNr/vnfNME/EoMdEraP4ZkUQek=
sigs.k8s.io/kustomize/kustomize/v5 v5.0.1/go.mod h1:Q8o+soB41Pn1y26eXzG9cniuECDpTJe2eKOA1fENCU8=
sigs.k8s.io/kustomize/kyaml v0.14.1 h1:c8iibius7l24G2wVAGZn/Va2wNys03GXLjYVIcFVxKA=
sigs.k8s.io/kustomize/kyaml v0.14.1/go.mod h1:AN1/IpawKilWD7V+YvQwRGUvuUOOWpjsHu6uHwonSF4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

8
ingressctl/main.go Normal file
View file

@ -0,0 +1,8 @@
package main
import "github.com/kubernetes/ingress-nginx/ingressctl/cmd"
func main() {
cmd.Execute()
}

View file

@ -1,19 +0,0 @@
//go:build mage
/*
Copyright 2023 The Kubernetes Authors.
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 main

View file

@ -1,31 +0,0 @@
//go:build mage
/*
Copyright 2023 The Kubernetes Authors.
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 main
//import (
// "github.com/magefile/mage/mg"
// "github.com/mysteriumnetwork/go-ci/commands"
//)
//
//type Go mg.Namespace
//
//// Checks for issues with go imports
//func (Go) CheckGoImports() error {
// return commands.GoImports("./...")
//}