Signed-off-by: James Strong <james.strong@chainguard.dev>
This commit is contained in:
James Strong 2023-06-14 09:10:34 -07:00
parent ff3d6bdf97
commit 1ae5d8df20
Failed to extract signature
5 changed files with 1196 additions and 66 deletions

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"`
}

View file

@ -14,70 +14,81 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package main
package cmd
import (
"context"
"errors"
"fmt"
"github.com/google/go-github/v48/github"
"golang.org/x/oauth2"
"gopkg.in/yaml.v3"
"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_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 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/kubernetes/k8s.io/main/registry.k8s.io/images/k8s-staging-ingress-nginx/images.yaml"
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){
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",
Use: "helm",
Short: "Start a new helm chart release",
Long: "Start a new helm chart release",
Run: func(cmd *cobra.Command, args []strings) {
Long: "Start a new helm chart release",
Run: func(cmd *cobra.Command, args []string) {
}
},
}
func init(){
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
@ -122,12 +133,12 @@ func init() {
}
// PromoteImage Creates PR into the k8s.io repo for promotion of ingress from staging to production
func (Release) PromoteImage(version, sha string) {
func PromoteImage(version, sha string) {
}
// Release Create a new release of ingress nginx controller
func (Release) NewRelease(version string) {
func NewRelease(version string) {
//newRelease := Release{}
//update ingress-nginx version
@ -142,11 +153,11 @@ func (Release) NewRelease(version string) {
//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)
mg.Deps(mg.F(Tag.BumpNginx, fmt.Sprintf("v%s", version)))
BumpNginx(fmt.Sprintf("v%s", version))
}
//update git controller tag controller-v$version
mg.Deps(mg.F(Tag.NewControllerTag, version))
NewControllerTag(version)
//make release notes
releaseNotes, err := makeReleaseNotes(version)
@ -172,7 +183,7 @@ func (Release) NewRelease(version string) {
}
//update helm chart app version
mg.Deps(mg.F(Helm.UpdateVersion, version))
//mg.Deps(mg.F(Helm.UpdateVersion, version))
releaseNotes.NewHelmChartVersion = currentChartVersion()
@ -187,7 +198,7 @@ func (Release) NewRelease(version string) {
//update static manifest
CheckIfError(updateStaticManifest(), "Error Updating Static manifests")
////update e2e docs
//update e2e docs
updateE2EDocs()
//update documentation with ingress-nginx version
@ -217,7 +228,7 @@ func updateIndexMD(old, new string) error {
// runs the hack/generate-deploy-scripts.sh
func updateE2EDocs() {
updates, err := sh.Output("./hack/generate-e2e-suite-doc.sh")
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 ")
@ -226,23 +237,13 @@ func updateE2EDocs() {
// The static deploy scripts use kustomize to generate them, this function ensures kustomize is installed
func installKustomize() error {
Info("Install Kustomize")
var g0 = sh.RunCmd("go")
// somewhere in your main code
err := g0("install", KUSTOMIZE_INSTALL_VERSION)
if err != nil {
return err
}
return nil
return sh.Command("go", "install", KUSTOMIZE_INSTALL_VERSION).Run()
}
func updateStaticManifest() error {
CheckIfError(installKustomize(), "error installing kustomize")
//hack/generate-deploy-scripts.sh
err := sh.RunV("./hack/generate-deploy-scripts.sh")
if err != nil {
return err
}
return nil
return sh.Command("./hack/generate-deploy-scripts.sh").Run()
}
//// CreateRelease Creates a new GitHub Release
@ -264,7 +265,7 @@ func githubClient() *github.Client {
}
// LatestCommitLogs Retrieves the commit log between the latest two controller versions.
func (Release) LatestCommitLogs() {
func LatestCommitLogs() {
commitLog := commitsBetweenTags()
for i, s := range commitLog {
Info("#%v Version %v", i, s)
@ -274,17 +275,17 @@ func (Release) LatestCommitLogs() {
func commitsBetweenTags() []string {
tags := getAllControllerTags()
Info("Getting Commits between %v and %v", tags[0], tags[1])
commitLog, err := git("log", "--full-history", "--pretty", "--oneline", fmt.Sprintf("%v..%v", tags[1], tags[0]))
commitLog, err := sh.Command("git", "log", "--full-history", "--pretty", "--oneline", fmt.Sprintf("%v..%v", tags[1], tags[0])).Output()
if commitLog == "" {
if len(commitLog) == 0 {
Warning("All Controller Tags is empty")
}
CheckIfError(err, "Retrieving Commit log")
return strings.Split(commitLog, "\n")
return strings.Split(string(commitLog), "\n")
}
// Generate Release Notes
func (Release) ReleaseNotes(newVersion string) error {
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)
@ -512,7 +513,7 @@ func downloadFile(url string) (string, error) {
}
// Latest returns latest Github Release
func (Release) Latest() error {
func ReleaseLatest() error {
r, _, err := latestRelease()
if err != nil {
ErrorF("Latest Release error %s", err)
@ -522,7 +523,7 @@ func (Release) Latest() error {
return nil
}
func (Release) ReleaseByTag(tag string) error {
func ReleaseByTag(tag string) error {
r, _, err := releaseByTag(tag)
if err != nil {
ErrorF("Release retrieve tag error %s", tag, err)
@ -545,7 +546,7 @@ func latestRelease() (*github.RepositoryRelease, *github.Response, error) {
}
// Copy Test function to copy a release
func (Release) Copy() error {
func ReleaseCopy() error {
ghClient := githubClient()
kRelease, _, err := ghClient.Repositories.GetLatestRelease(ctx, "kubernetes", "ingress-nginx")
if err != nil {

View file

@ -1,16 +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"
)
func getIngressNGINXVersion() (string, error) {
var tagCmd = &cobra.Command{
Use: "tag",
Short: "taggin information",
Long: "Retieves tagging information about the controller",
}
dat, err := os.ReadFile("TAG")
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
}