diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..99e910a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Checks** + +- [ ] version (v0.x.y) does support the feature +- [ ] I'm using an unreleased version of the controller I built from HEAD of the default branch + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment (please complete the following information):** + - Opvic Version [e.g. 0.18.2] + - Deployment Method [e.g. Helm] + - Helm Chart Version [if applicable] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..0e3a58f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,19 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..d289b49 --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,45 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bug' + - title: '🧰 Maintenance' + label: 'chore' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +template: | + ## What's Changed + + $CHANGES + +autolabeler: + - label: 'chore' + files: + - '*.md' + - label: 'bug' + branch: + - '/fix\/.+/' + title: + - '/fix/i' + - label: 'enhancement' + branch: + - '/feature\/.+/' + title: + - '/feature/i' diff --git a/.github/workflows/publish-canary-images.yaml b/.github/workflows/publish-images.yaml similarity index 81% rename from .github/workflows/publish-canary-images.yaml rename to .github/workflows/publish-images.yaml index ef9ef47..4868c8e 100644 --- a/.github/workflows/publish-canary-images.yaml +++ b/.github/workflows/publish-images.yaml @@ -1,4 +1,4 @@ -name: Publish Canary Images +name: Publish Images on: push: @@ -21,11 +21,21 @@ on: - 'Dockerfile' - 'Dockerfile.agent' - '.github/workflows/publish-canary-images.yaml' + release: + types: [published] jobs: control-plane: runs-on: ubuntu-latest steps: + - name: Get Version + id: version + uses: haya14busa/action-cond@v1 + with: + cond: ${{ github.event_name == 'release' }} + if_true: ${{ github.release.tag_name }} + if_false: "canary" + - name: Checkout uses: actions/checkout@v2 @@ -49,7 +59,7 @@ jobs: with: images: "ghcr.io/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}" tags: | - type=raw,value=canary + type=raw,value=${{ steps.version.outputs.value }} type=raw,value={{sha}} type=ref,event=branch @@ -66,7 +76,7 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max build-args: | - VERSION=canary + VERSION=${{ steps.version.outputs.value }} REVISION=${{ github.sha }} BRANCH=${{ github.ref }} BUILD_DATE=${{ steps.date.outputs.value }} @@ -75,6 +85,14 @@ jobs: agent: runs-on: ubuntu-latest steps: + - name: Get Version + id: version + uses: haya14busa/action-cond@v1 + with: + cond: ${{ github.event_name == 'release' }} + if_true: ${{ github.release.tag_name }} + if_false: "canary" + - name: Checkout uses: actions/checkout@v2 @@ -98,7 +116,7 @@ jobs: with: images: "ghcr.io/${{ github.event.repository.owner.login }}/${{ github.event.repository.name }}-agent" tags: | - type=raw,value=canary + type=raw,value=${{ steps.version.outputs.value }} type=raw,value={{sha}} type=ref,event=branch @@ -116,7 +134,7 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max build-args: | - VERSION=canary + VERSION=${{ steps.version.outputs.value }} REVISION=${{ github.sha }} BRANCH=${{ github.ref }} BUILD_DATE=${{ steps.date.outputs.value }} diff --git a/.github/workflows/release-drafter.yaml b/.github/workflows/release-drafter.yaml new file mode 100644 index 0000000..415ff06 --- /dev/null +++ b/.github/workflows/release-drafter.yaml @@ -0,0 +1,23 @@ +name: Release Drafter + +on: + push: + branches: + - main + paths: + - '!charts/**' + - '!.github/**' + pull_request: + types: [opened, reopened, synchronize] + branches: + - main + pull_request_target: + types: [opened, reopened, synchronize] + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/agent/agent.go b/agent/agent.go index d373eb3..7bb01ca 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -48,6 +48,7 @@ func (r *VersionTrackerReconciler) Reconcile(ctx context.Context, req ctrl.Reque var v v1alpha1.VersionTracker if err := r.Get(ctx, req.NamespacedName, &v); err != nil { log.Error(err, "unable to fetch VersionTracker") + reconciliationErrorsTotal.Inc() return ctrl.Result{}, client.IgnoreNotFound(err) } // Set defaults @@ -56,6 +57,7 @@ func (r *VersionTrackerReconciler) Reconcile(ctx context.Context, req ctrl.Reque err := v.Validate() if err != nil { log.Error(err, "failed to validate VersionTracker") + reconciliationErrorsTotal.Inc() return ctrl.Result{}, err } @@ -69,6 +71,7 @@ func (r *VersionTrackerReconciler) Reconcile(ctx context.Context, req ctrl.Reque selector, err := metav1.LabelSelectorAsSelector(v.Spec.Resources.Selector) if err != nil { log.Error(err, "failed to convert label selector to selector") + reconciliationErrorsTotal.Inc() return ctrl.Result{}, err } opts = append(opts, client.MatchingLabelsSelector{Selector: selector}) @@ -77,6 +80,7 @@ func (r *VersionTrackerReconciler) Reconcile(ctx context.Context, req ctrl.Reque resources, err := v.GetObjectList() if err != nil { log.Error(err, "failed to get resource ObjectList") + reconciliationErrorsTotal.Inc() return ctrl.Result{}, err } @@ -88,25 +92,29 @@ func (r *VersionTrackerReconciler) Reconcile(ctx context.Context, req ctrl.Reque return ctrl.Result{}, err } - // Extract versions from resources - sv := r.ExtractSubjectVersion(v, resources) + // Get items based on the resource type + items := GetItems(resources) + if len(items) == 0 { + log.Info("no resources found") + } else { + // Extract versions from resources + sv := r.ExtractSubjectVersion(v, items) + + // Ship the version information to the Control Plane + if len(sv.Versions) > 0 && r.Config.ControlPlaneUrl != "" { + err := r.ShipToControlPlane(sv) + if err != nil { + log.Error(err, "failed to ship the version to control plane") + reconciliationErrorsTotal.Inc() + return ctrl.Result{}, err + } + } + } - // elapsed := time.Since(start) lastReconciliationTimestamp.SetToCurrentTime() reconciliationDuration.Set(float64(elapsed.Milliseconds())) - - // Ship the version information to the Control Plane - if len(sv.Versions) > 0 && r.Config.ControlPlaneUrl != "" { - err := r.ShipToControlPlane(sv) - if err != nil { - log.Error(err, "failed to ship the version to control plane") - reconciliationErrorsTotal.Inc() - return ctrl.Result{}, err - } - } log.Info("done reconciling", "interval", r.Config.Interval) - return ctrl.Result{ RequeueAfter: r.Config.Interval, }, nil diff --git a/agent/extract_version.go b/agent/extract_version.go index ab5f784..7ed7e32 100644 --- a/agent/extract_version.go +++ b/agent/extract_version.go @@ -30,13 +30,18 @@ type Version struct { // ExtractSubjectVersion looks at the feild of each individuel resource and extracts the version // based on the extraction configuration in the VersionTracker -func (r *VersionTrackerReconciler) ExtractSubjectVersion(v v1alpha1.VersionTracker, resources client.ObjectList) SubjectVersion { +func (r *VersionTrackerReconciler) ExtractSubjectVersion(v v1alpha1.VersionTracker, items []interface{}) SubjectVersion { log := r.Log.WithName("extractor").WithValues("VersionTracker", fmt.Sprintf("%s/%s", v.ObjectMeta.Namespace, v.ObjectMeta.Name)) var version string var versions []string uniqueVersions := []string{} - items := GetItems(resources) lv := v.GetLocalVersion() + + if len(items) == 0 { + log.Info("no resource was found. skipping version extraction") + return SubjectVersion{} + } + appVersion := &SubjectVersion{ ID: v.Spec.Name, Namespace: v.ObjectMeta.Namespace, diff --git a/agent/shipper.go b/agent/shipper.go index c92c0f7..a634eb2 100644 --- a/agent/shipper.go +++ b/agent/shipper.go @@ -74,14 +74,15 @@ func (r *VersionTrackerReconciler) ShipToControlPlane(ver SubjectVersion) error shipperConf := &ShipperConfig{ URL: r.Config.ControlPlaneUrl, Token: r.Config.ControlPlaneAuthToken, - Timeout: time.Second * 30, - TLSVerify: false, + Timeout: time.Second * 10, + TLSVerify: true, } shipper := NewShipper(shipperConf) err := shipper.Post(r.PrepareThePayload(ver)) if err != nil { return err } + log.Info("successfully sent version info to the control plane") return nil } diff --git a/agent/utils.go b/agent/utils.go index b62a276..74dd522 100644 --- a/agent/utils.go +++ b/agent/utils.go @@ -11,13 +11,16 @@ import ( func getFeilds(jsonPath string, resource interface{}) ([]string, error) { fields, err := get.RelaxedJSONPathExpression(jsonPath) if err != nil { - + return nil, err } j := jsonpath.New("jsonpath") if err := j.Parse(fields); err != nil { - panic(err) + return nil, err } values, err := j.FindResults(resource) + if err != nil { + return nil, err + } valueStrings := []string{} for arrIx := range values { for valIx := range values[arrIx] { diff --git a/controlplane/version/version.go b/controlplane/version/version.go index 41e5b0e..6531e97 100644 --- a/controlplane/version/version.go +++ b/controlplane/version/version.go @@ -95,9 +95,9 @@ func (v *Versions) Latest() *version.Version { func (v *Versions) StringList() []string { vers := []string{} for _, version := range v.RemoteVersions { - vers = append(vers, version.String()) + vers = append(vers, version.Original()) } - return vers + return utils.RemoveDuplicateStr(vers) } func (v *Versions) GreaterThan() *Versions {