Skip to content

[apps] Add managed OpenSearch service - #1953

Merged
Andrei Kvapil (kvaps) merged 8 commits into
cozystack:mainfrom
matthieu-robin:opensearch
Mar 18, 2026
Merged

Andrei Kvapil (kvaps) merged 8 commits into
cozystack:mainfrom
matthieu-robin:opensearch

Conversation

@matthieu-robin

@matthieu-robin Matthieu ROBIN (matthieu-robin) commented Feb 2, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Add packages/apps/opensearch/ — managed OpenSearch application chart with multi-version support (v1/v2/v3), TLS, HTTP Basic auth, custom users, OpenSearch Dashboards, external access, topology spread policies
  • Add packages/system/opensearch-operator/ — wrapper around opster OpenSearch operator v2.8.0 with sysctl daemonset for vm.max_map_count
  • Add packages/system/opensearch-rd/ — ApplicationDefinition for Cozystack platform integration (dashboard UI, schema validation, resource exposure)

Details

  • Versions: v1 → 1.3.20, v2 → 2.11.1, v3 → 3.0.0
  • Security: Auto-generated admin credentials, TLS on transport + HTTP, bcrypt-hashed security config
  • Dashboards: Optional deployment with TLS, configurable replicas and resources
  • External access: LoadBalancer services for OpenSearch (9200) and Dashboards (5601) with DNS annotations
  • Tests: Comprehensive Helm test suite (opensearch, security, users)

Test plan

  • helm template renders correctly with default values
  • helm template renders correctly with dashboards, external access, and custom users enabled
  • Deploy on a test cluster with the operator installed
  • Verify OpenSearch cluster reaches green status
  • Verify Dashboards connectivity
  • Verify external access via LoadBalancer

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Managed OpenSearch charts and operator with CRDs, RBAC, external LoadBalancer services, per-user secrets, security/config secrets, dashboards, and a sysctl DaemonSet.
  • Documentation

    • New chart READMEs, values.yaml, and JSON schema documenting configuration, defaults, and version mappings.
  • Tests

    • Extensive manifest tests covering rendering, security, users, storage, topology, and version selection.
  • Chores

    • Build tooling, Makefiles, packaging ignores, and version update scripts added.

@dosubot dosubot Bot added size/XXL This PR changes 1000+ lines, ignoring generated files kind/feature Categorizes issue or PR as related to a new feature labels Feb 2, 2026
@coderabbitai

coderabbitai Bot commented Feb 2, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an OpenSearch Helm application chart, an OpenSearch Operator Helm chart (with many CRDs and operator resources), an opensearch-rd ApplicationDefinition package, packaging helpers/scripts/Makefiles, tests, and PackageSource declarations.

Changes

Cohort / File(s) Summary
App chart metadata & packaging
packages/apps/opensearch/Chart.yaml, packages/apps/opensearch/.helmignore, packages/apps/opensearch/Makefile, packages/apps/opensearch/charts/cozy-lib
New application chart metadata, packaging ignore, Makefile targets (generate/update), and local cozy-lib reference.
App values & schema
packages/apps/opensearch/values.yaml, packages/apps/opensearch/values.schema.json, packages/apps/opensearch/files/versions.yaml
Adds values.yaml, comprehensive JSON Schema for values, and generated version→image-tag mapping.
App templates
packages/apps/opensearch/templates/_versions.tpl, .../opensearch.yaml, .../security.yaml, .../external-svc.yaml, .../dashboard-resourcemap.yaml, .../users.yaml
New Helm templates producing OpenSearchCluster CR and WorkloadMonitor, secrets (admin/security/credentials), per-user Secrets, external Services, dashboard RBAC, and version mapping helper; contains conditional rendering and upgrade-safe secret preservation logic.
App tests
packages/apps/opensearch/tests/opensearch_test.yaml, .../security_test.yaml, .../users_test.yaml
Adds extensive YAML-driven rendering tests validating chart output across versions, storage, topology, security secrets, dashboards, and user-secret generation.
App utilities
packages/apps/opensearch/hack/update-versions.sh
Script to discover latest OpenSearch image tags and update files/versions.yaml.
Operator packaging & Makefiles
packages/system/opensearch-operator/Chart.yaml, .../.helmignore, .../Makefile, .../values.yaml
Operator chart metadata, packaging ignore, Makefile to pull upstream operator chart, and operator values including CRD install toggle and kube-rbac-proxy settings.
Operator chart & templates
packages/system/opensearch-operator/charts/opensearch-operator/Chart.yaml, .../templates/_helpers.tpl, .../templates/*controller-manager*.yaml, .../templates/*rbac*.yaml, .../templates/sysctl-daemonset.yaml, .../templates/*metrics*.yaml
Adds upstream operator chart files: helpers, controller-manager Deployment, ServiceAccount, RBAC (roles/clusterroles, bindings), metrics Service, manager ConfigMap, sysctl DaemonSet, and kube-rbac-proxy support.
Operator CRDs
packages/system/opensearch-operator/charts/opensearch-operator/files/opensearch.opster.io_*.yaml
Introduces many opensearch.opster.io CRDs (ActionGroup, ComponentTemplate, IndexTemplate, ISMPolicy, Role, SnapshotPolicy, Tenant, UserRoleBinding, User, etc.) with OpenAPIv3 schemas and status subresources.
Operator chart docs & changelog
packages/system/opensearch-operator/charts/opensearch-operator/README.md, .../CHANGELOG.md
Adds README and changelog for the operator chart.
Resource definition (rd) package
packages/system/opensearch-rd/Chart.yaml, packages/system/opensearch-rd/Makefile, packages/system/opensearch-rd/cozyrds/opensearch.yaml, packages/system/opensearch-rd/templates/cozyrd.yaml, packages/system/opensearch-rd/values.yaml
Adds ApplicationDefinition for OpenSearch (inline OpenAPI schema), release/dashboard/secrets/services mappings, and template to emit cozyrds files.
Package sources
packages/core/platform/sources/opensearch-application.yaml, packages/core/platform/sources/opensearch-operator.yaml
Adds PackageSource manifests referencing the new packages and their install variants.
Docs & README
packages/apps/opensearch/README.md
Adds chart README documenting parameters and defaults.

Sequence Diagram(s)

sequenceDiagram
  participant PS as PackageSource
  participant OCI as OCIRepository
  participant Helm as Helm/PackageManager
  participant K8s as Kubernetes API
  participant Operator as OpenSearch Operator
  participant OSCluster as OpenSearchCluster CR

  PS->>OCI: reference charts/artifacts
  Helm->>OCI: pull charts (app + operator)
  Helm->>K8s: install app chart (renders OpenSearchCluster, Secrets, Services)
  Helm->>K8s: optionally install operator chart (CRDs if enabled)
  K8s->>Operator: CRDs + OpenSearchCluster created
  Operator->>K8s: reconcile -> create/manage StatefulSets/Services/Secrets
  Operator->>OSCluster: update status (managed state, conditions)
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Suggested labels

size:XL

Suggested reviewers

  • lllamnyp
  • nbykov0

Poem

🐰 I hopped through charts and CRDs with delight,
Tucked secrets safe and templated names just right.
Values, tests, and Makefiles neatly spun,
An operator, charts, and sysctl work — all done.
🥕 Hop on, reviewers — this rabbit’s bite is light!

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

Migrating from UI to YAML configuration.

Use the @coderabbitai configuration command in a PR comment to get a dump of all your UI settings in YAML format. You can then edit this YAML file and upload it to the root of your repository to configure CodeRabbit programmatically.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello Matthieu ROBIN (@matthieu-robin), I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a comprehensive managed OpenSearch service for the Cozystack platform. It includes the application chart, an operator wrapper, and platform integration components, enhancing the ability to deploy and manage OpenSearch clusters with security and ease.

Highlights

  • Managed OpenSearch Application: Adds a managed OpenSearch application chart with multi-version support (v1/v2/v3), TLS, HTTP Basic auth, custom users, OpenSearch Dashboards, external access, and topology spread policies.
  • OpenSearch Operator Wrapper: Includes a wrapper around the opster OpenSearch operator v2.8.0, along with a sysctl daemonset for vm.max_map_count.
  • Cozystack Platform Integration: Introduces an ApplicationDefinition for Cozystack platform integration, featuring a dashboard UI, schema validation, and resource exposure.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment Gemini (@gemini-code-assist) Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on Gemini (@gemini-code-assist) comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🤖 Fix all issues with AI agents
In `@packages/apps/opensearch/Chart.yaml`:
- Around line 1-7: Update the Chart.yaml metadata so the appVersion reflects the
chart's default supported OpenSearch release: change the appVersion value from
"2.18" to "2.11.1" to match the chart's default version mapping (the
Chart.yaml's appVersion field and the chart's version reference).

In `@packages/apps/opensearch/files/versions.yaml`:
- Around line 1-5: Add a new maintenance script
packages/apps/opensearch/hack/update-versions.sh (modeled after the other apps'
hack/update-versions.sh) that queries the OpenSearch releases/tags (GitHub API
or official index), extracts semver tags, groups by major version, picks the
latest patch/release for each major, and writes the mapping into
files/versions.yaml in the same YAML format ("v3": "3.0.0", ...); make the
script executable, ensure it safely updates files/versions.yaml (atomic write),
includes minimal error handling and an option to run locally/CI, and add/mention
the script in repository docs or CI tasks consistent with the other
packages/apps maintenance scripts.

In `@packages/apps/opensearch/README.md`:
- Around line 96-123: Fix markdownlint warnings by normalizing pipe spacing in
the "Parameters" and "Resource Presets" tables (ensure single space around each
cell separator and consistent header divider formatting) and replace bare URLs
in the "Support" section with markdown links or reference-style links so they
are not bare; update the README.md tables shown under the Parameters and
Resource Presets headings and the Support section URLs (lines referenced in the
review) to use properly spaced table pipes and wrapped/link-formatted URLs.
- Around line 94-100: Rename the README section heading from "## Configuration
Parameters" to exactly "## Parameters" so the docs generator recognizes it;
locate the heading string "## Configuration Parameters" in the file and replace
it with "## Parameters" (or update the generator if you prefer, but the quick
fix is to change the heading text).

In `@packages/apps/opensearch/templates/security.yaml`:
- Around line 100-117: Add the missing standard labels to the credentials
Secret: update the Secret metadata for the resource named "{{ .Release.Name
}}-credentials" to include labels "app.kubernetes.io/name" and
"app.kubernetes.io/instance" (matching the values used on the other secrets,
e.g., the chart name and release instance), so the Secret's metadata.labels
mirror those on admin-credentials and security-config; keep the existing
metadata.name and type unchanged.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml`:
- Around line 86-89: The imagePullSecrets block is mis-indented: the template
uses toYaml .Values.manager.imagePullSecrets | nindent 6 which places the keys
at the wrong column under spec; change the indentation to nindent 8 so
imagePullSecrets and its entries align correctly under spec. Locate the
imagePullSecrets conditional around the manager chart (references:
imagePullSecrets, .Values.manager.imagePullSecrets, nindent) and replace nindent
6 with nindent 8 to fix alignment.
- Around line 75-77: The extraEnv block in the Helm template uses incorrect
indentation: change the nindent call for .Values.manager.extraEnv from nindent 8
to nindent 10 so its rendered env entries align with the other environment
variables in the opensearch-operator-controller-manager-deployment template
(look for the block referencing .Values.manager.extraEnv and the surrounding env
var lines around the existing env entries).

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-manager-config-cm.yaml`:
- Around line 1-17: This change adds a vendored Helm template
(opensearch-operator-manager-config-cm.yaml) that creates a ConfigMap containing
ControllerManagerConfig (key controller_manager_config.yaml with apiVersion
controller-runtime.sigs.k8s.io/v1alpha1), which must not be edited in place;
revert this file from the vendored charts and instead apply the customization
through the umbrella chart or a post-render step: remove the added template from
the vendored chart, then provide the same ConfigMap content via your umbrella
chart’s values/overlays (or a kustomize/post-renderer patch) so the resulting
release contains the ConfigMap named by the template expression using include
"opensearch-operator.fullname" without modifying upstream chart files.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-metrics-reader-cr.yaml`:
- Line 4: The metadata.name template uses unquoted Helm templating which
triggers yamllint; wrap the entire templated expression in quotes so the value
remains a single YAML string — update the metadata.name that uses include
"opensearch-operator.fullname" and .Release.Namespace (the line with
metadata.name: {{ include "opensearch-operator.fullname" . }}-{{
.Release.Namespace }}-metrics-reader) to be a quoted string containing the
combined template.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-proxy-rolebinding.yaml`:
- Around line 1-27: The template currently emits a RoleBinding when
.Values.useRoleBindings is true which cannot grant cluster-scoped permissions
needed for tokenreviews/subjectaccessreviews; change the logic in
opensearch-operator-proxy-rolebinding.yaml so it always creates a
ClusterRoleBinding (i.e., remove or override the .Values.useRoleBindings branch
and ensure kind: ClusterRoleBinding and apiVersion: rbac.authorization.k8s.io/v1
are used), keeping the existing roleRef (name using include
"opensearch-operator.fullname") and subjects (service account from include
"opensearch-operator.serviceAccountName" and .Release.Namespace) unchanged.
Ensure no code path emits kind: RoleBinding for the proxy binding.

In `@packages/system/opensearch-operator/Makefile`:
- Around line 6-10: The Makefile update target currently runs helm pull without
pinning a chart version; modify the helm pull invocation in the update target so
it includes a --version 2.8.0 flag (i.e., update the helm pull
opensearch-operator/opensearch-operator command in the update recipe) to ensure
reproducible builds.

In `@packages/system/opensearch-operator/values.yaml`:
- Around line 1-4: Replace the empty-string value used for
opensearch-operator.manager.watchNamespace with a null/omitted value to match
upstream idiom: update the YAML so that watchNamespace is either written as
watchNamespace: (no value) or watchNamespace: null under the opensearch-operator
→ manager section so Helm treats it as unset and the chart produces cluster-wide
watching.
🧹 Nitpick comments (8)
packages/system/opensearch-operator/charts/opensearch-operator/CHANGELOG.md (1)

29-42: Minor categorization inconsistencies in changelog entries.

Lines 32 and 42 describe additions ("Added missing spec", "Added README.md") but are placed under the "Changed" subsection instead of "Added". While this doesn't follow Keep a Changelog conventions strictly, these entries likely come from the upstream operator and should not be modified in a vendored chart.

Note: If this chart is vendored as-is from upstream, these inconsistencies should be left unchanged to maintain fidelity with the original source.

packages/system/opensearch-operator/Makefile (1)

6-6: Consider declaring update as a phony target.

Since update doesn't create a file, declaring it as .PHONY ensures it always runs when invoked, even if a file named update happens to exist.

Proposed fix
+.PHONY: update
 update:
 	rm -rf charts
packages/system/opensearch-operator/templates/sysctl-daemonset.yaml (2)

20-40: Privileged container is required for sysctl operations.

The Checkov warnings (CKV_K8S_16, CKV_K8S_20, CKV_K8S_23) about privileged containers are expected false positives in this context—modifying kernel parameters via sysctl -w requires privileged access.

However, consider these improvements for the persistence logic:

  1. Use /etc/sysctl.d/ drop-in directory instead of appending to sysctl.conf - this is the modern convention and avoids modifying the main config file
  2. The grep pattern could match existing lines with different values, leaving the old value in place and just appending a duplicate
♻️ Proposed improvement using sysctl.d drop-in
           command:
             - sh
             - -c
             - |
               sysctl -w vm.max_map_count=262144
-              # Keep the value persistent by writing to sysctl.conf if writable
-              if [ -w /host-etc/sysctl.conf ]; then
-                grep -q "vm.max_map_count" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
+              # Keep the value persistent using sysctl.d drop-in (preferred over modifying sysctl.conf)
+              if [ -d /host-etc/sysctl.d ] && [ -w /host-etc/sysctl.d ]; then
+                echo "vm.max_map_count=262144" > /host-etc/sysctl.d/99-opensearch.conf
               fi

55-59: Consider narrowing the hostPath scope.

Mounting the entire /etc directory is broader than necessary. If you adopt the sysctl.d approach, you could mount only /etc/sysctl.d to reduce the attack surface.

♻️ Narrower hostPath mount
       volumes:
         - name: host-etc
           hostPath:
-            path: /etc
-            type: Directory
+            path: /etc/sysctl.d
+            type: DirectoryOrCreate

And update the volumeMount accordingly:

           volumeMounts:
-            - name: host-etc
-              mountPath: /host-etc
+            - name: host-sysctl-d
+              mountPath: /host-sysctl-d
packages/system/opensearch-operator/charts/opensearch-operator/values.yaml (1)

49-53: Consider using IfNotPresent for image pull policy in production.

pullPolicy: "Always" can cause unnecessary network traffic and potential availability issues if the registry is unreachable. For production workloads, IfNotPresent is typically preferred, with explicit image tags for version control.

Suggested change
   image:
     repository: opensearchproject/opensearch-operator
     ## tag default uses appVersion from Chart.yaml, to override specify tag tag: "v1.1"
     tag: ""
-    pullPolicy: "Always"
+    pullPolicy: "IfNotPresent"
packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-leader-election-rolebinding-rb.yaml (1)

9-11: Consider adding namespace to the ServiceAccount subject.

The ServiceAccount subject is missing the namespace field. While this typically defaults to the RoleBinding's namespace for namespace-scoped Roles, explicitly specifying it improves clarity and prevents potential issues if the ServiceAccount is expected to be in a specific namespace.

Suggested change
 subjects:
 - kind: ServiceAccount
   name: {{ include "opensearch-operator.serviceAccountName" . }}
+  namespace: {{ .Release.Namespace }}
packages/apps/opensearch/values.schema.json (1)

162-175: Consider documenting or restricting low-memory presets.

The description correctly notes "OpenSearch requires minimum 2Gi memory," but the enum still allows nano, micro, and small presets which may provide insufficient memory. This could lead to OOMKilled pods or cluster instability.

Options to consider:

  1. Remove undersized presets from the enum
  2. Add validation in the template to enforce minimum memory
  3. Keep as-is if users are expected to understand the requirements (current approach)
packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml (1)

30-31: Verbose logging level may impact performance in production.

--v=10 sets maximum verbosity for kube-rbac-proxy. This can generate excessive logs and impact performance. Consider reducing to a lower level (e.g., --v=2) for production deployments.

💡 Suggested fix
         - --proxy-endpoints-port=10443
         - --logtostderr=true
-        - --v=10
+        - --v=0

Comment thread packages/apps/opensearch/Chart.yaml Outdated
Comment thread packages/apps/opensearch/files/versions.yaml Outdated
Comment thread packages/apps/opensearch/README.md Outdated
Comment thread packages/apps/opensearch/README.md Outdated
Comment thread packages/apps/opensearch/templates/security.yaml
Comment on lines +1 to +17
apiVersion: v1
data:
controller_manager_config.yaml: |
apiVersion: controller-runtime.sigs.k8s.io/v1alpha1
kind: ControllerManagerConfig
health:
healthProbeBindAddress: :8081
metrics:
bindAddress: 127.0.0.1:8080
webhook:
port: 9443
leaderElection:
leaderElect: true
resourceName: a867c7dc.opensearch.opster.io
kind: ConfigMap
metadata:
name: {{ include "opensearch-operator.fullname" . }}-manager-config

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid direct edits in vendored chart templates.

Line 1-17 adds a template under the vendored charts/opensearch-operator tree. Per repo guidance, customizations should be applied via the umbrella chart (values/overrides or post-render) instead of editing vendored templates directly. As per coding guidelines: **/*.yaml: Do NOT directly edit upstream Helm charts in vendored charts directory; use proper chart vendoring mechanisms.

🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 17-17: syntax error: expected , but found ''

(syntax)

🤖 Prompt for AI Agents
In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-manager-config-cm.yaml`
around lines 1 - 17, This change adds a vendored Helm template
(opensearch-operator-manager-config-cm.yaml) that creates a ConfigMap containing
ControllerManagerConfig (key controller_manager_config.yaml with apiVersion
controller-runtime.sigs.k8s.io/v1alpha1), which must not be edited in place;
revert this file from the vendored charts and instead apply the customization
through the umbrella chart or a post-render step: remove the added template from
the vendored chart, then provide the same ConfigMap content via your umbrella
chart’s values/overlays (or a kustomize/post-renderer patch) so the resulting
release contains the ConfigMap named by the template expression using include
"opensearch-operator.fullname" without modifying upstream chart files.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Quote templated metadata.name to satisfy yamllint.

Line 4 triggers a YAML parse error for the linter due to the unquoted {{ ... }} template. Quoting keeps Helm behavior and fixes linting.

🛠️ Suggested fix
-  name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader
+  name: "{{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader
name: "{{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader"
🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 4-4: syntax error: expected , but found ''

(syntax)

🤖 Prompt for AI Agents
In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-metrics-reader-cr.yaml`
at line 4, The metadata.name template uses unquoted Helm templating which
triggers yamllint; wrap the entire templated expression in quotes so the value
remains a single YAML string — update the metadata.name that uses include
"opensearch-operator.fullname" and .Release.Namespace (the line with
metadata.name: {{ include "opensearch-operator.fullname" . }}-{{
.Release.Namespace }}-metrics-reader) to be a quoted string containing the
combined template.

Comment thread packages/system/opensearch-operator/Makefile Outdated
Comment thread packages/system/opensearch-operator/values.yaml

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a managed OpenSearch service to the Cozystack platform, which is a significant and well-executed addition. The changes include a comprehensive Helm chart for the OpenSearch application, a wrapper for the OpenSearch operator, and the necessary ApplicationDefinition for platform integration. The application chart is particularly impressive, with multi-version support, robust security configurations that handle upgrades gracefully, and extensive Helm tests. The operator wrapper correctly sets up the upstream operator for cluster-wide monitoring and includes a DaemonSet to configure necessary kernel parameters on nodes. Overall, the quality of the contribution is high. I have identified one critical issue that will prevent the application chart from deploying, and a couple of medium-severity issues related to metadata correctness and resource naming consistency that should be addressed to improve maintainability.

Comment on lines +3 to +5
"v3": "3.0.0"
"v2": "2.11.1"
"v1": "1.3.20"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The format of this YAML file is invalid. It appears to be a list of strings rather than a valid YAML mapping. This will cause the fromYaml function in templates/_versions.tpl to fail during template rendering, which will break the deployment of the chart. The file should be structured as a single YAML mapping.

The script that generates this file (likely hack/update-versions.sh) should be updated to produce valid YAML.

v3: "3.0.0"
v2: "2.11.1"
v1: "1.3.20"

Comment thread packages/apps/opensearch/Chart.yaml Outdated
icon: /logos/opensearch.svg
type: application
version: 0.0.0 # Placeholder, the actual version will be automatically set during the build process
appVersion: "2.18"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The appVersion is set to "2.18", which appears to be incorrect. According to files/versions.yaml and the README.md, the default version for this chart is v2, which corresponds to OpenSearch 2.11.1. To avoid confusion and provide accurate metadata, the appVersion should reflect the version of the application being deployed by default.

appVersion: "2.11.1"

Comment on lines +7 to +18
name: opensearch-sysctl-setter
labels:
app.kubernetes.io/name: opensearch-sysctl-setter
app.kubernetes.io/component: sysctl
spec:
selector:
matchLabels:
app.kubernetes.io/name: opensearch-sysctl-setter
template:
metadata:
labels:
app.kubernetes.io/name: opensearch-sysctl-setter

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The DaemonSet name and its labels are hardcoded. This is inconsistent with other resources in the Helm chart ecosystem, which typically use release-based naming to ensure uniqueness and avoid conflicts. Hardcoded names can be problematic, especially for cluster-scoped or widely-used resources. It is recommended to use dynamic names based on the release name for consistency and to prevent potential conflicts.

  name: {{ .Release.Name }}-sysctl-setter
  labels:
    app.kubernetes.io/name: {{ .Release.Name }}-sysctl-setter
    app.kubernetes.io/component: sysctl
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: {{ .Release.Name }}-sysctl-setter
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ .Release.Name }}-sysctl-setter

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@packages/apps/opensearch/Makefile`:
- Around line 1-11: The Makefile's update target references a missing script
("hack/update-versions.sh") and uses a plain "make" invocation; add the missing
hack/update-versions.sh script (matching behavior from other app packages) into
this package so the update target can run, and change the recursive invocation
in the update target from "make generate" to use "$(MAKE) generate" to propagate
make flags and jobserver settings; ensure the Makefile targets "generate" and
"update" remain as-is and the new script is executable and implements the same
version-update logic used by the other app packages.

In `@packages/apps/opensearch/templates/opensearch.yaml`:
- Around line 61-72: Add validation to values.schema.json to ensure at least one
node role is enabled by requiring nodeRoles.master, nodeRoles.data,
nodeRoles.ingest or nodeRoles.ml to be true; implement this by adding an anyOf
(or oneOf) clause that includes four subschemas each asserting
nodeRoles.<master|data|ingest|ml> : { "const": true } (or equivalent
boolean-true check), so the schema fails if all four flags are false, and update
the chart README to document the requirement if you prefer a documented
constraint instead of schema enforcement.

In `@packages/apps/opensearch/values.schema.json`:
- Around line 91-100: The schema for nodeRoles currently sets "default": {}
while also declaring required keys ["data","ingest","master","ml"], causing a
conflict; update the nodeRoles entry (the "nodeRoles" object in the JSON schema)
by either removing the "required" array for nodeRoles or supplying a complete
default object that includes keys data, ingest, master, and ml with appropriate
boolean/default values so the default satisfies the required properties.
- Around line 22-30: The dashboards schema declares "default": {} but also lists
required properties ["enabled","replicas","resourcesPreset"], causing validation
failure; fix by either removing the required array from the dashboards object
(so nested properties rely on their own defaults) or by replacing the empty
default with a complete default object that includes enabled, replicas and
resourcesPreset values; update the "dashboards" schema (the dashboards object in
values.schema.json) accordingly and ensure nested property defaults remain
intact.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml`:
- Around line 1-13: Move the custom Service resource (the controller-manager
metrics Service named via {{ include "opensearch-operator.fullname" .
}}-controller-manager-metrics-service) out of the vendored subchart and into the
parent umbrella chart's templates directory; delete the duplicate file from the
subchart so there’s no conflicting resource, keep the same metadata (labels:
control-plane: controller-manager), spec (ports port: 8443 targetPort: https,
selector: control-plane: controller-manager), and retain the same Helm fullname
include reference so names remain stable, and update chart dependencies or
values if the parent needs to reference any subchart values used by this
template.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-manager-rolebinding.yaml`:
- Around line 1-27: The RoleBinding branch controlled by .Values.useRoleBindings
incorrectly attempts to grant cluster-scoped permissions (the manager-role
ClusterRole includes namespace resource rules) which RoleBinding cannot
authorize; update the template so either (a) remove the RoleBinding branch and
always emit a ClusterRoleBinding for the manager-role, or (b) keep the
.Values.useRoleBindings conditional but ensure that the ClusterRole
(manager-role) does not contain cluster-scoped namespace rules when rendering a
RoleBinding—move namespace-related rules to only be rendered when emitting the
ClusterRoleBinding branch (the template block generating ClusterRoleBinding and
the manager-role rules must include namespace resource permissions, while the
RoleBinding branch must only reference namespaced resources or be removed).

In `@packages/system/opensearch-operator/templates/sysctl-daemonset.yaml`:
- Around line 35-40: Update the initContainer persistence logic around the
sysctl change (the block containing "sysctl -w vm.max_map_count=262144" and the
check of /host-etc/sysctl.conf) so it atomically ensures a single non-commented
setting: check for a non-commented key using a stricter pattern (e.g. grep -qE
'^\s*vm.max_map_count=' /host-etc/sysctl.conf 2>/dev/null) and if present use
sed -i to replace the value (sed -i
's/^\s*vm.max_map_count=.*/vm.max_map_count=262144/') else append the line; keep
the existing writable check (if [ -w /host-etc/sysctl.conf ]) and
suppress/handle grep errors to avoid appending duplicates on failures.

In `@packages/system/opensearch-rd/cozyrds/opensearch.yaml`:
- Around line 10-11: The dashboards and nodeRoles schemas declare required
properties but set default to an empty object, causing validation failures when
an empty object is provided; update the defaults so they include the required
keys (for dashboards include enabled, replicas, resourcesPreset and a default
resources object as appropriate) or alternatively remove the required arrays
from dashboards and nodeRoles; specifically modify the openAPISchema entries for
"dashboards" and "nodeRoles" so the "default" for dashboards is an object
containing enabled:false (or current default), replicas:1,
resourcesPreset:"medium" (and resources:{} if needed) and the "default" for
nodeRoles is an object with data:true, ingest:true, master:true, ml:false
(matching the properties), or drop the "required" fields from each schema.
🧹 Nitpick comments (7)
packages/system/opensearch-operator/templates/sysctl-daemonset.yaml (2)

6-18: Consider adding Helm templating for namespace and standard labels.

The DaemonSet lacks Helm templating for namespace and standard Kubernetes labels like app.kubernetes.io/instance, app.kubernetes.io/managed-by, and helm.sh/chart. This is common practice for Helm-managed resources.

♻️ Suggested enhancement
 metadata:
   name: opensearch-sysctl-setter
+  namespace: {{ .Release.Namespace }}
   labels:
     app.kubernetes.io/name: opensearch-sysctl-setter
     app.kubernetes.io/component: sysctl
+    app.kubernetes.io/instance: {{ .Release.Name }}
+    app.kubernetes.io/managed-by: {{ .Release.Service }}
+    helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }}

55-59: Consider mounting only /etc/sysctl.conf instead of entire /etc.

Mounting the entire /etc directory is broader than necessary and increases the attack surface. The initContainer only needs access to /etc/sysctl.conf.

🔒 Proposed fix to reduce host filesystem exposure
       volumes:
-        - name: host-etc
+        - name: host-sysctl-conf
           hostPath:
-            path: /etc
-            type: Directory
+            path: /etc/sysctl.conf
+            type: FileOrCreate

And update the volumeMount accordingly:

           volumeMounts:
-            - name: host-etc
-              mountPath: /host-etc
+            - name: host-sysctl-conf
+              mountPath: /host-etc/sysctl.conf
               readOnly: false

Then simplify the command:

-              if [ -w /host-etc/sysctl.conf ]; then
-                grep -q "vm.max_map_count" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
+              if [ -w /host-etc/sysctl.conf ]; then
+                grep -qE "^[[:space:]]*vm\.max_map_count[[:space:]]*=" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
               fi
packages/system/opensearch-rd/templates/cozyrd.yaml (1)

1-4: Ensure deterministic ordering of CozyRD documents.

range over .Files.Glob is non-deterministic, which can lead to unstable rendered manifests and test diffs. Sorting the paths avoids that.

♻️ Suggested change
-{{- range $path, $_ := .Files.Glob "cozyrds/*" }}
+{{- $files := .Files.Glob "cozyrds/*" }}
+{{- range $path := (keys $files | sortAlpha) }}
 ---
-{{ $.Files.Get $path }}
+{{ $files.Get $path }}
 {{- end }}
packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-sa.yaml (1)

1-6: Consider adding namespace and standard labels.

The ServiceAccount template is functional but could benefit from adding the release namespace and standard Helm labels for consistency with other resources in the chart.

♻️ Optional enhancement
 {{- if .Values.serviceAccount.create -}}
 apiVersion: v1
 kind: ServiceAccount
 metadata:
   name: {{ include "opensearch-operator.serviceAccountName" . }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "opensearch-operator.labels" . | nindent 4 }}
 {{- end -}}

Note: The YAMLlint error on line 1 is a false positive—Helm template directives like {{- are valid syntax that linters unaware of Helm cannot parse.

packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-leader-election-role-role.yaml (1)

37-48: Leader-election Role grants ServiceMonitor CRUD—verify necessity.

If ServiceMonitors are managed by the controller, this permission is better placed in the manager ClusterRole. Otherwise, removing it tightens least-privilege.

✂️ Suggested reduction (if not required)
-- apiGroups:
-  - monitoring.coreos.com
-  resources:
-  - servicemonitors
-  verbs:
-  - create
-  - delete
-  - get
-  - list
-  - patch
-  - update
-  - watch
packages/apps/opensearch/templates/dashboard-resourcemap.yaml (1)

10-16: Gate external service names in RBAC rules on .Values.external.

The Role includes {{ .Release.Name }}-external (line 12) unconditionally and {{ .Release.Name }}-dashboards-external (line 15) only when dashboards are enabled. However, both external services are created only when .Values.external is true (see external-svc.yaml line 1). The RBAC rules should align with actual service creation to avoid referencing non-existent resources.

Update lines 12 and 15 to gate external services on the same conditions used for their creation:

♻️ Proposed fix
   resourceNames:
   - {{ .Release.Name }}
+  {{- if .Values.external }}
   - {{ .Release.Name }}-external
+  {{- end }}
   {{- if .Values.dashboards.enabled }}
   - {{ .Release.Name }}-dashboards
+  {{- if .Values.external }}
   - {{ .Release.Name }}-dashboards-external
+  {{- end }}
   {{- end }}
packages/apps/opensearch/values.schema.json (1)

162-174: Documentation note: small presets may not meet OpenSearch memory requirements.

The description correctly notes "OpenSearch requires minimum 2Gi memory," but the enum includes nano, micro, and small presets which may fall below this threshold. Consider either removing those options from the enum or adding a validation note in the description.

Comment thread packages/apps/opensearch/Makefile Outdated
Comment on lines +1 to +11
include ../../../hack/package.mk

.PHONY: generate update

generate:
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
../../../hack/update-crd.sh

update:
hack/update-versions.sh
make generate

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check if hack/update-versions.sh exists in packages/apps/opensearch/
find packages/apps/opensearch/ -name "update-versions.sh" -o -name "hack" -type d

Repository: cozystack/cozystack

Length of output: 45


🏁 Script executed:

# Check the structure of packages/apps/opensearch/
ls -la packages/apps/opensearch/

Repository: cozystack/cozystack

Length of output: 834


🏁 Script executed:

# Check if package.mk exists and what targets it provides
cat packages/apps/opensearch/../../../hack/package.mk | head -50

Repository: cozystack/cozystack

Length of output: 1307


🏁 Script executed:

# Check if the opensearch package has charts directory (Helm umbrella pattern)
find packages/apps/opensearch/ -type d -name "charts"

Repository: cozystack/cozystack

Length of output: 94


🏁 Script executed:

# Check if update-versions.sh exists anywhere in the packages/apps directory
find packages/apps/ -name "update-versions.sh" 2>/dev/null

Repository: cozystack/cozystack

Length of output: 292


🏁 Script executed:

# Check if there's a hack directory at the root or elsewhere that might be referenced
find packages/apps/opensearch -type d -name "hack"

Repository: cozystack/cozystack

Length of output: 45


The Makefile references a non-existent script hack/update-versions.sh on line 10.

The opensearch package is missing the hack/update-versions.sh script that exists in other app packages (kubernetes, mongodb, mysql, postgres, redis). The make update target will fail until this script is added.

Additionally, use $(MAKE) instead of make for the recursive call on line 11 to properly propagate make flags and job server settings.

♻️ Suggested improvement
 update:
 	hack/update-versions.sh
-	make generate
+	$(MAKE) generate
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
include ../../../hack/package.mk
.PHONY: generate update
generate:
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
../../../hack/update-crd.sh
update:
hack/update-versions.sh
make generate
include ../../../hack/package.mk
.PHONY: generate update
generate:
cozyvalues-gen -v values.yaml -s values.schema.json -r README.md
../../../hack/update-crd.sh
update:
hack/update-versions.sh
$(MAKE) generate
🧰 Tools
🪛 checkmake (0.2.2)

[warning] 3-3: Missing required phony target "all"

(minphony)


[warning] 3-3: Missing required phony target "clean"

(minphony)


[warning] 3-3: Missing required phony target "test"

(minphony)

🤖 Prompt for AI Agents
In `@packages/apps/opensearch/Makefile` around lines 1 - 11, The Makefile's update
target references a missing script ("hack/update-versions.sh") and uses a plain
"make" invocation; add the missing hack/update-versions.sh script (matching
behavior from other app packages) into this package so the update target can
run, and change the recursive invocation in the update target from "make
generate" to use "$(MAKE) generate" to propagate make flags and jobserver
settings; ensure the Makefile targets "generate" and "update" remain as-is and
the new script is executable and implements the same version-update logic used
by the other app packages.

Comment thread packages/apps/opensearch/templates/opensearch.yaml
Comment thread packages/apps/opensearch/values.schema.json
Comment thread packages/apps/opensearch/values.schema.json
Comment on lines +1 to +13
apiVersion: v1
kind: Service
metadata:
labels:
control-plane: controller-manager
name: {{ include "opensearch-operator.fullname" . }}-controller-manager-metrics-service
spec:
ports:
- name: https
port: 8443
targetPort: https
selector:
control-plane: controller-manager

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the local opensearch-operator package structure
echo "=== Local Package Structure ==="
find packages/system/opensearch-operator -type f -name "*.yaml" | head -30

echo ""
echo "=== Directory Tree ==="
ls -la packages/system/opensearch-operator/ 2>/dev/null || echo "Directory not found"

Repository: cozystack/cozystack

Length of output: 3518


🌐 Web query:

opensearch-k8s-operator Helm chart templates opensearch-operator-controller-manager-metrics-service

💡 Result:

That Service is rendered by the operator Helm chart (the chart you install as opensearch-operator/opensearch-operator) that ships with the OpenSearch K8s Operator repo. (github.com)

Because the chart name is opensearch-operator, Helm’s default fullname logic typically prefixes resources with your release name, which is why you see:

  • opensearch-operator-controller-manager-metrics-service (release opensearch-operator) (github.com)

To locate the exact template file that renders it (and edit/override it), the most reliable way is to pull the chart and grep locally:

helm repo add opensearch-operator https://opensearch-project.github.io/opensearch-k8s-operator/
helm repo update

helm pull opensearch-operator/opensearch-operator --untar
cd opensearch-operator

grep -R "controller-manager-metrics-service" -n templates
# also try:
grep -R "metrics-service" -n templates

If you only have the rendered manifest (cluster already installed), you can map it back to the template with:

helm get manifest opensearch-operator | grep -n "name: opensearch-operator-controller-manager-metrics-service" -n

This Service exists to expose the operator’s Prometheus-style metrics endpoint (the operator documents “Operator Monitoring” and “Controller Metrics”). (opensearch-project.github.io)

Citations:


🏁 Script executed:

#!/bin/bash
# Check the Chart.yaml of the vendored chart to understand versioning
echo "=== Vendored Chart Information ==="
cat packages/system/opensearch-operator/charts/opensearch-operator/Chart.yaml

echo ""
echo "=== Check if .helmignore or similar indicates this is vendored ==="
cat packages/system/opensearch-operator/.helmignore 2>/dev/null || echo "No .helmignore found"

echo ""
echo "=== Check git history for this file ==="
git log --oneline -10 -- packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml 2>/dev/null || echo "No git history available"

echo ""
echo "=== List all templates in the vendored chart ==="
ls -la packages/system/opensearch-operator/charts/opensearch-operator/templates/

Repository: cozystack/cozystack

Length of output: 2126


🌐 Web query:

opensearch-project/opensearch-k8s-operator Helm chart metrics-service template GitHub

💡 Result:

In opensearch-project/opensearch-k8s-operator, the Helm charts are under the repo’s charts/ directory. (github.com)

To find the metrics-service template on GitHub, search within the repo for it (it should be under one of the chart template directories, e.g. charts/<chart-name>/templates/). (github.com)

Use GitHub code search like:

repo:opensearch-project/opensearch-k8s-operator metrics-service
repo:opensearch-project/opensearch-k8s-operator path:charts "metrics" "Service"
repo:opensearch-project/opensearch-k8s-operator path:charts/ "ServiceMonitor"

Citations:


🏁 Script executed:

#!/bin/bash
# Query the upstream opensearch-k8s-operator repo for the metrics-service template
echo "=== Checking upstream opensearch-k8s-operator repository ==="

# Try to fetch the file from GitHub at version 2.8.0
UPSTREAM_URL="https://raw.githubusercontent.com/opensearch-project/opensearch-k8s-operator/2.8.0/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml"
echo "Checking: $UPSTREAM_URL"
if curl -s -o /tmp/upstream.yaml -w "%{http_code}" "$UPSTREAM_URL" | grep -q "200"; then
  echo "✓ File EXISTS in upstream v2.8.0"
  echo ""
  echo "=== Content comparison ==="
  echo "Local file:"
  cat packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml
  echo ""
  echo "Upstream file:"
  cat /tmp/upstream.yaml
  echo ""
  echo "=== Diff ==="
  diff <(cat packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml) /tmp/upstream.yaml || echo "(Files differ)"
else
  echo "✗ File NOT found in upstream v2.8.0 (HTTP status: $(curl -s -o /dev/null -w "%{http_code}" "$UPSTREAM_URL"))"
fi

echo ""
echo "=== Checking if there are similar files in upstream chart ==="
curl -s "https://api.github.com/repos/opensearch-project/opensearch-k8s-operator/contents/charts/opensearch-operator/templates?ref=2.8.0" | jq -r '.[].name' 2>/dev/null | head -20

Repository: cozystack/cozystack

Length of output: 435


🏁 Script executed:

#!/bin/bash
# Verify by checking a known upstream template
echo "=== Verifying with a known template that SHOULD be in upstream ==="

# Check for the deployment template which should definitely exist
DEPLOY_URL="https://raw.githubusercontent.com/opensearch-project/opensearch-k8s-operator/2.8.0/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml"
echo "Checking upstream deployment template:"
curl -s -o /dev/null -w "HTTP Status: %{http_code}\n" "$DEPLOY_URL"

echo ""
echo "=== Checking if metrics-service exists in parent chart ==="
cat packages/system/opensearch-operator/templates/ 2>/dev/null && ls -la packages/system/opensearch-operator/templates/ || echo "Parent templates directory contents listed above"

echo ""
echo "=== Checking recent commits to understand intent ==="
git log --oneline --all -20 -- packages/system/opensearch-operator/ 2>/dev/null | head -10

Repository: cozystack/cozystack

Length of output: 395


🏁 Script executed:

#!/bin/bash
# Check if version 2.8.0 exists and what's the actual structure
echo "=== Checking for v2.8.0 tag in upstream ==="
curl -s "https://api.github.com/repos/opensearch-project/opensearch-k8s-operator/tags" | jq -r '.[] | .name' | grep -E "^2\." | head -10

echo ""
echo "=== Checking master/main branch chart structure ==="
curl -s "https://api.github.com/repos/opensearch-project/opensearch-k8s-operator/contents/charts?ref=main" 2>/dev/null | jq -r '.[].name' 2>/dev/null || echo "Could not access main branch"

echo ""
echo "=== Checking if opensearch-operator-manager-role-cr.yaml exists in upstream ==="
curl -s -o /dev/null -w "HTTP Status: %{http_code}\n" "https://raw.githubusercontent.com/opensearch-project/opensearch-k8s-operator/main/charts/opensearch-operator/templates/opensearch-operator-manager-role-cr.yaml"

echo ""
echo "=== Final verification: Check full commit details ==="
git show 80909916 --stat 2>/dev/null | head -30 || echo "Commit info not available"

Repository: cozystack/cozystack

Length of output: 1914


🏁 Script executed:

#!/bin/bash
# The commit message mentions "opster v2.8.0" - check if this is from Opster organization
echo "=== Checking Opster/opensearch-k8s-operator repository ==="
curl -s -o /dev/null -w "Opster Metrics Service - HTTP Status: %{http_code}\n" "https://raw.githubusercontent.com/Opster/opensearch-k8s-operator/2.8.0/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml"

echo ""
echo "=== Checking if parent chart has custom additions ==="
ls -la packages/system/opensearch-operator/templates/

echo ""
echo "=== Content of parent chart templates ==="
cat packages/system/opensearch-operator/templates/sysctl-daemonset.yaml 2>/dev/null | head -20

echo ""
echo "=== Check parent chart values to see how it references subchart ==="
cat packages/system/opensearch-operator/values.yaml
</details>

Repository: cozystack/cozystack

Length of output: 1288


Move the metrics-service template to the parent umbrella chart.

This Service template is a custom addition (not from the upstream Opster operator chart). Per coding guidelines, it should be placed in packages/system/opensearch-operator/templates/ rather than in the vendored subchart directory at packages/system/opensearch-operator/charts/opensearch-operator/templates/. The umbrella pattern requires custom resources to be defined in the parent chart, while charts/ should contain only unmodified vendored charts. Reference the subchart resources from the parent chart if needed.

🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 6-6: syntax error: expected , but found ''

(syntax)

🤖 Prompt for AI Agents
In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-metrics-service-svc.yaml`
around lines 1 - 13, Move the custom Service resource (the controller-manager
metrics Service named via {{ include "opensearch-operator.fullname" .
}}-controller-manager-metrics-service) out of the vendored subchart and into the
parent umbrella chart's templates directory; delete the duplicate file from the
subchart so there’s no conflicting resource, keep the same metadata (labels:
control-plane: controller-manager), spec (ports port: 8443 targetPort: https,
selector: control-plane: controller-manager), and retain the same Helm fullname
include reference so names remain stable, and update chart dependencies or
values if the parent needs to reference any subchart values used by this
template.

Comment on lines +1 to +27
{{- if .Values.useRoleBindings }}
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-role
subjects:
- kind: ServiceAccount
name: {{ include "opensearch-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- else }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-manager-role
subjects:
- kind: ServiceAccount
name: {{ include "opensearch-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find all files in the opensearch-operator chart directory
find packages/system/opensearch-operator/charts/opensearch-operator -type f -name "*.yaml" | head -20

# Search for manager-role definition across the chart
rg "kind: ClusterRole" packages/system/opensearch-operator/charts/opensearch-operator -A 100 | grep -A 100 "manager-role"

Repository: cozystack/cozystack

Length of output: 19308


🏁 Script executed:

cat packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-manager-role-cr.yaml

Repository: cozystack/cozystack

Length of output: 5800


RoleBinding branch cannot grant namespace permissions—remove or fix conditionally.

The manager-role ClusterRole includes permissions for the namespaces resource (a cluster-scoped resource), but the RoleBinding branch of this template cannot grant permissions for cluster-scoped resources. When useRoleBindings=true, namespace management permissions will silently fail to apply, breaking operator functionality.

Either:

  1. Remove the RoleBinding branch and always use ClusterRoleBinding, or
  2. Conditionally generate the namespace rule only in the ClusterRoleBinding branch
🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 1-1: syntax error: expected the node content, but found '-'

(syntax)

🤖 Prompt for AI Agents
In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-manager-rolebinding.yaml`
around lines 1 - 27, The RoleBinding branch controlled by
.Values.useRoleBindings incorrectly attempts to grant cluster-scoped permissions
(the manager-role ClusterRole includes namespace resource rules) which
RoleBinding cannot authorize; update the template so either (a) remove the
RoleBinding branch and always emit a ClusterRoleBinding for the manager-role, or
(b) keep the .Values.useRoleBindings conditional but ensure that the ClusterRole
(manager-role) does not contain cluster-scoped namespace rules when rendering a
RoleBinding—move namespace-related rules to only be rendered when emitting the
ClusterRoleBinding branch (the template block generating ClusterRoleBinding and
the manager-role rules must include namespace resource permissions, while the
RoleBinding branch must only reference namespaced resources or be removed).

Comment on lines +35 to +40
- |
sysctl -w vm.max_map_count=262144
# Keep the value persistent by writing to sysctl.conf if writable
if [ -w /host-etc/sysctl.conf ]; then
grep -q "vm.max_map_count" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
fi

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Sysctl persistence logic may create duplicate entries.

The current logic has two issues:

  1. If the initContainer runs multiple times (pod restarts), and grep fails for any reason (e.g., permission issue, malformed file), duplicates will be appended.
  2. The grep pattern "vm.max_map_count" would also match commented lines like # vm.max_map_count=....

Consider using a more robust pattern or idempotent approach.

🛠️ Proposed fix with stricter pattern
             - |
               sysctl -w vm.max_map_count=262144
               # Keep the value persistent by writing to sysctl.conf if writable
               if [ -w /host-etc/sysctl.conf ]; then
-                grep -q "vm.max_map_count" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
+                grep -qE "^[[:space:]]*vm\.max_map_count[[:space:]]*=" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
               fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- |
sysctl -w vm.max_map_count=262144
# Keep the value persistent by writing to sysctl.conf if writable
if [ -w /host-etc/sysctl.conf ]; then
grep -q "vm.max_map_count" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
fi
- |
sysctl -w vm.max_map_count=262144
# Keep the value persistent by writing to sysctl.conf if writable
if [ -w /host-etc/sysctl.conf ]; then
grep -qE "^[[:space:]]*vm\.max_map_count[[:space:]]*=" /host-etc/sysctl.conf || echo "vm.max_map_count=262144" >> /host-etc/sysctl.conf
fi
🤖 Prompt for AI Agents
In `@packages/system/opensearch-operator/templates/sysctl-daemonset.yaml` around
lines 35 - 40, Update the initContainer persistence logic around the sysctl
change (the block containing "sysctl -w vm.max_map_count=262144" and the check
of /host-etc/sysctl.conf) so it atomically ensures a single non-commented
setting: check for a non-commented key using a stricter pattern (e.g. grep -qE
'^\s*vm.max_map_count=' /host-etc/sysctl.conf 2>/dev/null) and if present use
sed -i to replace the value (sed -i
's/^\s*vm.max_map_count=.*/vm.max_map_count=262144/') else append the line; keep
the existing writable check (if [ -w /host-etc/sysctl.conf ]) and
suppress/handle grep errors to avoid appending duplicates on failures.

Comment on lines +10 to +11
openAPISchema: |-
{"title":"Chart Values","type":"object","properties":{"external":{"description":"Enable external access from outside the cluster.","type":"boolean","default":false},"images":{"description":"Container images used by the operator.","type":"object","default":{},"properties":{"opensearch":{"description":"OpenSearch image.","type":"string","default":""}}},"dashboards":{"description":"OpenSearch Dashboards configuration.","type":"object","default":{},"required":["enabled","replicas","resourcesPreset"],"properties":{"enabled":{"description":"Enable OpenSearch Dashboards deployment.","type":"boolean","default":false},"replicas":{"description":"Number of Dashboards replicas.","type":"integer","default":1},"resources":{"description":"Explicit CPU and memory configuration for Dashboards.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each node.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each node.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset for Dashboards.","type":"string","default":"medium","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]}}},"nodeRoles":{"description":"Node roles configuration.","type":"object","default":{},"required":["data","ingest","master","ml"],"properties":{"data":{"description":"Enable data role.","type":"boolean","default":true},"ingest":{"description":"Enable ingest role.","type":"boolean","default":true},"master":{"description":"Enable cluster_manager role.","type":"boolean","default":true},"ml":{"description":"Enable machine learning role.","type":"boolean","default":false}}},"replicas":{"description":"Number of OpenSearch nodes in the cluster.","type":"integer","default":3},"resources":{"description":"Explicit CPU and memory configuration for each OpenSearch node. When omitted, the preset defined in `resourcesPreset` is applied.","type":"object","default":{},"properties":{"cpu":{"description":"CPU available to each node.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"memory":{"description":"Memory (RAM) available to each node.","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true}}},"resourcesPreset":{"description":"Default sizing preset used when `resources` is omitted. OpenSearch requires minimum 2Gi memory.","type":"string","default":"large","enum":["nano","micro","small","medium","large","xlarge","2xlarge"]},"size":{"description":"Persistent Volume Claim size available for application data.","default":"10Gi","pattern":"^(\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\\+|-)?(([0-9]+(\\.[0-9]*)?)|(\\.[0-9]+))))?$","anyOf":[{"type":"integer"},{"type":"string"}],"x-kubernetes-int-or-string":true},"storageClass":{"description":"StorageClass used to store the data.","type":"string","default":""},"topologySpreadPolicy":{"description":"How strictly to enforce pod distribution across nodes and zones.","type":"string","default":"soft","enum":["soft","hard"]},"users":{"description":"Custom OpenSearch users configuration map.","type":"object","default":{},"additionalProperties":{"type":"object","properties":{"password":{"description":"Password for the user (auto-generated if omitted).","type":"string"},"roles":{"description":"List of OpenSearch roles.","type":"array","items":{"type":"string"}}}}},"version":{"description":"OpenSearch major version to deploy.","type":"string","default":"v2","enum":["v3","v2","v1"]}}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align dashboards/nodeRoles defaults with their required lists.

Both objects declare required properties but default to {}. If a user (or UI) submits an empty object, validation will fail. Consider either removing the required lists or setting defaults that include the required fields.

🤖 Prompt for AI Agents
In `@packages/system/opensearch-rd/cozyrds/opensearch.yaml` around lines 10 - 11,
The dashboards and nodeRoles schemas declare required properties but set default
to an empty object, causing validation failures when an empty object is
provided; update the defaults so they include the required keys (for dashboards
include enabled, replicas, resourcesPreset and a default resources object as
appropriate) or alternatively remove the required arrays from dashboards and
nodeRoles; specifically modify the openAPISchema entries for "dashboards" and
"nodeRoles" so the "default" for dashboards is an object containing
enabled:false (or current default), replicas:1, resourcesPreset:"medium" (and
resources:{} if needed) and the "default" for nodeRoles is an object with
data:true, ingest:true, master:true, ml:false (matching the properties), or drop
the "required" fields from each schema.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@packages/apps/opensearch/hack/update-versions.sh`:
- Around line 36-49: The script currently only warns when a major version has no
stable tag (inside the for loop using SUPPORTED_MAJOR_VERSIONS, TAGS, LATEST and
appending to VERSIONS_FILE), which yields an incomplete versions.yaml; change
the else branch to print a clear error to stderr and exit non‑zero (e.g., echo
"ERROR: No stable release found for major version ${MAJOR}" >&2; exit 1) so the
script fails fast; additionally, to avoid producing a partial VERSIONS_FILE,
build the output into a temporary file first and only move/rename it to
VERSIONS_FILE after the loop completes successfully.

In `@packages/apps/opensearch/templates/opensearch.yaml`:
- Around line 7-14: The template is creating a first-party OpenSearchCluster CR
(OpenSearchCluster in templates/opensearch.yaml) instead of acting as an
umbrella chart wrapping a vendored upstream operator; vendor the upstream
OpenSearch Operator chart into charts/opensearch-operator/, add it as a
dependency in Chart.yaml (name/version/repository entry), remove or stop
committing the operator CR as a direct upstream resource, and instead keep this
chart as the umbrella by placing only configuration templates/values that supply
the operator with the cluster spec (e.g., move the spec currently in
templates/opensearch.yaml into values and let the vendored operator chart render
the OpenSearchCluster using those values or create a minimal template that
references .Values to instantiate the CR via the operator); ensure metadata.name
and spec.general.serviceName still use {{ .Release.Name }} and that the operator
is installed from charts/opensearch-operator rather than defining operator
resources here.
- Around line 87-99: The WorkloadMonitor CRD is setting spec.version to the Helm
chart version ({{ .Chart.Version }}) instead of the OpenSearch application
version; update the template so the WorkloadMonitor resource (kind:
WorkloadMonitor) sets spec.version to the application value by replacing the
current use of .Chart.Version with .Values.version (i.e., set version: {{
.Values.version }}) so spec.version reflects the deployed OpenSearch version.

In `@packages/apps/opensearch/templates/security.yaml`:
- Around line 1-7: The template currently generates a new $password whenever
$existingAdminCreds is missing even if $existingSecurityConfig exists, which
risks password drift; update the conditional logic around
$existingAdminCreds/$existingSecurityConfig so that if $existingSecurityConfig
exists but $existingAdminCreds is absent you first attempt a fallback lookup for
the user-facing credentials Secret (the Secret that contains the live user
password used by clients) and reuse its password if found, and only if no
recoverable password can be found then fail fast with an explicit error/log
rather than silently generating a new random $password; reference the symbols
$existingSecurityConfig, $existingAdminCreds, $password and the
"*-admin-credentials" and "security-config" Secret names when making the change.

In `@packages/apps/opensearch/values.schema.json`:
- Around line 79-92: The "images" schema declares "required": ["opensearch"] but
sets "default": {}, causing a schema conflict; fix by either removing the
"required" array from the images object or by setting a complete default object
that includes the opensearch property (e.g., a default string for the
"opensearch" property) so the default satisfies the required constraint; update
the images object's "default" or its "required" entry accordingly, referencing
the images object and the opensearch property in the schema.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-metrics-reader-cr.yaml`:
- Around line 1-9: This ClusterRole manifest under the vendored chart (defines
kind: ClusterRole with metadata name using {{ include
"opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader and
rule nonResourceURLs: [/metrics]) must not be edited in-place; move this
resource into your umbrella/wrapper chart's templates directory, create a
corresponding values entry (e.g., enableMetricsReader: true) and wiring (via
values/labels) so the wrapper chart renders the ClusterRole with the same
name/template include and namespace, and remove/ignore the vendored copy; ensure
the wrapper template retains the same metadata name expression and verb/rules so
behavior is identical.
🧹 Nitpick comments (2)
packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml (1)

25-25: Unusual nil-check pattern for conditional container.

The condition eq (.Values.kubeRbacProxy.enable | toString) "<nil>" is an unconventional way to check for unset values. Consider using the standard Helm idiom with default.

♻️ Suggested improvement
-      {{- if or (.Values.kubeRbacProxy.enable) (eq (.Values.kubeRbacProxy.enable | toString) "<nil>") }}
+      {{- if ne .Values.kubeRbacProxy.enable false }}

Or ensure kubeRbacProxy.enable defaults to true in values.yaml and use:

{{- if .Values.kubeRbacProxy.enable }}
packages/apps/opensearch/templates/dashboard-resourcemap.yaml (1)

33-39: Consider adopting the inline nindent pattern for consistency with tenant.yaml and vpc.yaml.

The current separate-line pattern produces valid YAML, but other templates use subjects: {{- include "cozy-lib.rbac.subjectsForTenantAndAccessLevel" (list "use" .Release.Namespace) | nindent 2 }} on the same line. For consistency across the codebase, consider aligning with this cleaner style.

Comment on lines +36 to +49
for MAJOR in $SUPPORTED_MAJOR_VERSIONS; do
# Find the latest stable release for this major version
LATEST=$(echo "$TAGS" \
| grep -E "^${MAJOR}\.[0-9]+\.[0-9]+$" \
| sort -t. -k1,1n -k2,2n -k3,3n \
| tail -1)

if [ -n "$LATEST" ]; then
echo "v${MAJOR}: latest tag is ${LATEST}"
echo "\"v${MAJOR}\": \"${LATEST}\"" >> "${VERSIONS_FILE}"
else
echo "WARNING: No stable release found for major version ${MAJOR}" >&2
fi
done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

fd "update-versions.sh" -t f

Repository: cozystack/cozystack

Length of output: 341


🏁 Script executed:

cat -n "packages/apps/opensearch/hack/update-versions.sh"

Repository: cozystack/cozystack

Length of output: 2072


🏁 Script executed:

rg "versions\.yaml" packages/apps/opensearch/ -t yaml -t sh

Repository: cozystack/cozystack

Length of output: 165


🏁 Script executed:

rg "versions\.yaml" packages/apps/opensearch/ --no-filename

Repository: cozystack/cozystack

Length of output: 283


🏁 Script executed:

rg "versions\.yaml" packages/apps/opensearch/ -B2 -A2

Repository: cozystack/cozystack

Length of output: 1234


🏁 Script executed:

cat -n "packages/apps/opensearch/templates/_versions.tpl"

Repository: cozystack/cozystack

Length of output: 657


🏁 Script executed:

git ls-files packages/apps/opensearch/files/versions.yaml

Repository: cozystack/cozystack

Length of output: 107


🏁 Script executed:

cat "packages/apps/opensearch/files/versions.yaml"

Repository: cozystack/cozystack

Length of output: 231


Fail fast when a major version has no stable tag.
The script currently warns and continues writing versions.yaml if a registry query returns no matching stable release for a major version. This creates an incomplete file that silently breaks downstream Helm deployments—the template at templates/_versions.tpl will fail with "Invalid version" when a key is missing, but the actual problem originates in this script failing to detect the issue.

💡 Proposed fix (fail the script if any major version is missing)
 echo "# OpenSearch version mapping (major version -> image tag)" > "${VERSIONS_FILE}"
 echo "# Auto-generated by hack/update-versions.sh - do not edit manually" >> "${VERSIONS_FILE}"
 
+missing=false
 for MAJOR in $SUPPORTED_MAJOR_VERSIONS; do
     # Find the latest stable release for this major version
     LATEST=$(echo "$TAGS" \
         | grep -E "^${MAJOR}\.[0-9]+\.[0-9]+$" \
         | sort -t. -k1,1n -k2,2n -k3,3n \
         | tail -1)
 
     if [ -n "$LATEST" ]; then
         echo "v${MAJOR}: latest tag is ${LATEST}"
         echo "\"v${MAJOR}\": \"${LATEST}\"" >> "${VERSIONS_FILE}"
     else
         echo "WARNING: No stable release found for major version ${MAJOR}" >&2
+        missing=true
     fi
 done
+
+if [ "$missing" = true ]; then
+  echo "Error: missing one or more major version mappings; refusing to write incomplete ${VERSIONS_FILE}" >&2
+  exit 1
+fi
🤖 Prompt for AI Agents
In `@packages/apps/opensearch/hack/update-versions.sh` around lines 36 - 49, The
script currently only warns when a major version has no stable tag (inside the
for loop using SUPPORTED_MAJOR_VERSIONS, TAGS, LATEST and appending to
VERSIONS_FILE), which yields an incomplete versions.yaml; change the else branch
to print a clear error to stderr and exit non‑zero (e.g., echo "ERROR: No stable
release found for major version ${MAJOR}" >&2; exit 1) so the script fails fast;
additionally, to avoid producing a partial VERSIONS_FILE, build the output into
a temporary file first and only move/rename it to VERSIONS_FILE after the loop
completes successfully.

Comment on lines +7 to +14
apiVersion: opensearch.opster.io/v1
kind: OpenSearchCluster
metadata:
name: {{ .Release.Name }}
spec:
general:
serviceName: {{ .Release.Name }}
version: {{ include "opensearch.versionMap" $ }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect chart dependencies and vendored charts directory
echo "=== Chart.yaml content ==="
cat packages/apps/opensearch/Chart.yaml

echo -e "\n=== Checking for charts directory ==="
if [ -d packages/apps/opensearch/charts ]; then
  echo "charts/ directory exists"
  ls -la packages/apps/opensearch/charts
else
  echo "charts/ directory does NOT exist"
fi

echo -e "\n=== Checking templates directory ==="
ls -la packages/apps/opensearch/templates/ 2>/dev/null || echo "templates directory not found"

echo -e "\n=== Checking overall opensearch package structure ==="
find packages/apps/opensearch -type f -name "*.yaml" | head -20

Repository: cozystack/cozystack

Length of output: 1772


Refactor chart to follow umbrella pattern with vendored upstream OpenSearch Operator chart.

This chart currently defines first-party resources directly instead of acting as an umbrella wrapper. Per packages/apps/** standards, vendor the upstream OpenSearch Operator chart under charts/opensearch-operator/ and configure dependencies in Chart.yaml, then use this chart to manage the operator deployment. The charts/ directory should contain the vendored operator chart, not library references.

🤖 Prompt for AI Agents
In `@packages/apps/opensearch/templates/opensearch.yaml` around lines 7 - 14, The
template is creating a first-party OpenSearchCluster CR (OpenSearchCluster in
templates/opensearch.yaml) instead of acting as an umbrella chart wrapping a
vendored upstream operator; vendor the upstream OpenSearch Operator chart into
charts/opensearch-operator/, add it as a dependency in Chart.yaml
(name/version/repository entry), remove or stop committing the operator CR as a
direct upstream resource, and instead keep this chart as the umbrella by placing
only configuration templates/values that supply the operator with the cluster
spec (e.g., move the spec currently in templates/opensearch.yaml into values and
let the vendored operator chart render the OpenSearchCluster using those values
or create a minimal template that references .Values to instantiate the CR via
the operator); ensure metadata.name and spec.general.serviceName still use {{
.Release.Name }} and that the operator is installed from
charts/opensearch-operator rather than defining operator resources here.

Comment on lines +87 to +99
# WorkloadMonitor tracks OpenSearch pods
apiVersion: cozystack.io/v1alpha1
kind: WorkloadMonitor
metadata:
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicas }}
minReplicas: 1
kind: opensearch
type: opensearch
selector:
opster.io/opensearch-cluster: {{ .Release.Name }}
version: {{ .Chart.Version }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for WorkloadMonitor CRD definition and schema
find . -type f \( -name "*.yaml" -o -name "*.yml" \) -exec rg -l "kind:\s*WorkloadMonitor|WorkloadMonitor.*CRD" {} \;

Repository: cozystack/cozystack

Length of output: 1751


🏁 Script executed:

# Look for WorkloadMonitor CRD or schema definition
rg -i "workloadmonitor" --type yaml -C5 | head -100

Repository: cozystack/cozystack

Length of output: 6642


🏁 Script executed:

# Check the opensearch values file to see what version fields are available
find packages/apps/opensearch -name "values*.yaml" -o -name "values*.yml"

Repository: cozystack/cozystack

Length of output: 99


🏁 Script executed:

# Read the WorkloadMonitor CRD to understand spec.version semantics
cat packages/system/cozystack-controller/definitions/cozystack.io_workloadmonitors.yaml

Repository: cozystack/cozystack

Length of output: 4172


🏁 Script executed:

# Read opensearch values to see what version fields are available
cat packages/apps/opensearch/values.yaml

Repository: cozystack/cozystack

Length of output: 3479


🏁 Script executed:

# Check how other packages use spec.version in WorkloadMonitor
grep -A10 "spec:" packages/apps/kafka/templates/workloadmonitor.yaml
grep -A10 "spec:" packages/apps/mongodb/templates/mongodb.yaml
grep -A10 "spec:" packages/apps/mysql/templates/workloadmonitor.yaml

Repository: cozystack/cozystack

Length of output: 1289


Use OpenSearch application version instead of chart version for spec.version.
The WorkloadMonitor CRD field spec.version is documented as "Version specifies the version of the workload". Currently it uses {{ .Chart.Version }} (the Helm chart version), but the opensearch chart has values.version available that specifies the actual OpenSearch application version (v1, v2, v3). To accurately track the deployed OpenSearch version, use version: {{ .Values.version }} instead.

Current code snippet
spec:
  replicas: {{ .Values.replicas }}
  minReplicas: 1
  kind: opensearch
  type: opensearch
  selector:
    opster.io/opensearch-cluster: {{ .Release.Name }}
  version: {{ .Chart.Version }}
🤖 Prompt for AI Agents
In `@packages/apps/opensearch/templates/opensearch.yaml` around lines 87 - 99, The
WorkloadMonitor CRD is setting spec.version to the Helm chart version ({{
.Chart.Version }}) instead of the OpenSearch application version; update the
template so the WorkloadMonitor resource (kind: WorkloadMonitor) sets
spec.version to the application value by replacing the current use of
.Chart.Version with .Values.version (i.e., set version: {{ .Values.version }})
so spec.version reflects the deployed OpenSearch version.

Comment on lines +1 to +7
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- $existingAdminCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-admin-credentials" .Release.Name) }}
{{- $existingSecurityConfig := lookup "v1" "Secret" .Release.Namespace (printf "%s-security-config" .Release.Name) }}
{{- $password := randAlphaNum 32 }}
{{- if and $existingAdminCreds (hasKey $existingAdminCreds.data "password") }}
{{- $password = index $existingAdminCreds.data "password" | b64dec }}
{{- end }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Prevent password drift when security-config exists without admin creds.

If the security-config Secret exists but *-admin-credentials was deleted, Lines 4–7 generate a new password while reusing the old hash from internal_users.yml, making operator/admin access fail. Consider falling back to an existing user-facing credentials Secret or failing fast when no recoverable password exists.

🔧 Possible guard/fallback
 {{- $existingAdminCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-admin-credentials" .Release.Name) }}
 {{- $existingSecurityConfig := lookup "v1" "Secret" .Release.Namespace (printf "%s-security-config" .Release.Name) }}
+{{- $existingUserCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}
 {{- $password := randAlphaNum 32 }}
 {{- if and $existingAdminCreds (hasKey $existingAdminCreds.data "password") }}
 {{- $password = index $existingAdminCreds.data "password" | b64dec }}
+{{- else if and $existingUserCreds (hasKey $existingUserCreds.data "password") }}
+{{- $password = index $existingUserCreds.data "password" | b64dec }}
 {{- end }}
+{{- if and $existingSecurityConfig (not (or $existingAdminCreds $existingUserCreds)) }}
+{{- fail "security-config exists but no credentials Secret found to recover admin password" }}
+{{- end }}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- $existingAdminCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-admin-credentials" .Release.Name) }}
{{- $existingSecurityConfig := lookup "v1" "Secret" .Release.Namespace (printf "%s-security-config" .Release.Name) }}
{{- $password := randAlphaNum 32 }}
{{- if and $existingAdminCreds (hasKey $existingAdminCreds.data "password") }}
{{- $password = index $existingAdminCreds.data "password" | b64dec }}
{{- end }}
{{- $clusterDomain := (index .Values._cluster "cluster-domain") | default "cozy.local" }}
{{- $existingAdminCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-admin-credentials" .Release.Name) }}
{{- $existingSecurityConfig := lookup "v1" "Secret" .Release.Namespace (printf "%s-security-config" .Release.Name) }}
{{- $existingUserCreds := lookup "v1" "Secret" .Release.Namespace (printf "%s-credentials" .Release.Name) }}
{{- $password := randAlphaNum 32 }}
{{- if and $existingAdminCreds (hasKey $existingAdminCreds.data "password") }}
{{- $password = index $existingAdminCreds.data "password" | b64dec }}
{{- else if and $existingUserCreds (hasKey $existingUserCreds.data "password") }}
{{- $password = index $existingUserCreds.data "password" | b64dec }}
{{- end }}
{{- if and $existingSecurityConfig (not (or $existingAdminCreds $existingUserCreds)) }}
{{- fail "security-config exists but no credentials Secret found to recover admin password" }}
{{- end }}
🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 1-1: syntax error: expected the node content, but found '-'

(syntax)

🤖 Prompt for AI Agents
In `@packages/apps/opensearch/templates/security.yaml` around lines 1 - 7, The
template currently generates a new $password whenever $existingAdminCreds is
missing even if $existingSecurityConfig exists, which risks password drift;
update the conditional logic around $existingAdminCreds/$existingSecurityConfig
so that if $existingSecurityConfig exists but $existingAdminCreds is absent you
first attempt a fallback lookup for the user-facing credentials Secret (the
Secret that contains the live user password used by clients) and reuse its
password if found, and only if no recoverable password can be found then fail
fast with an explicit error/log rather than silently generating a new random
$password; reference the symbols $existingSecurityConfig, $existingAdminCreds,
$password and the "*-admin-credentials" and "security-config" Secret names when
making the change.

Comment thread packages/apps/opensearch/values.schema.json
Comment on lines +1 to +9
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader
rules:
- nonResourceURLs:
- /metrics
verbs:
- get

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid editing vendored chart templates directly.

This file lives under charts/ (vendored upstream chart). Repo guidelines require keeping vendored charts untouched and placing custom resources in the umbrella chart. Please move this ClusterRole manifest into the wrapper chart’s own templates/ and wire it via values/labels as needed.

As per coding guidelines: “packages/system/**: Use Helm Chart umbrella pattern with vendored upstream charts in charts/ directory” and “**/*.yaml: Do NOT directly edit upstream Helm charts in vendored charts directory; use proper chart vendoring mechanisms.”

🧰 Tools
🪛 YAMLlint (1.38.0)

[error] 4-4: syntax error: expected , but found ''

(syntax)

🤖 Prompt for AI Agents
In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-metrics-reader-cr.yaml`
around lines 1 - 9, This ClusterRole manifest under the vendored chart (defines
kind: ClusterRole with metadata name using {{ include
"opensearch-operator.fullname" . }}-{{ .Release.Namespace }}-metrics-reader and
rule nonResourceURLs: [/metrics]) must not be edited in-place; move this
resource into your umbrella/wrapper chart's templates directory, create a
corresponding values entry (e.g., enableMetricsReader: true) and wiring (via
values/labels) so the wrapper chart renders the ClusterRole with the same
name/template include and namespace, and remove/ignore the vendored copy; ensure
the wrapper template retains the same metadata name expression and verb/rules so
behavior is identical.

@kvaps

Copy link
Copy Markdown
Member

Matthieu ROBIN (@matthieu-robin) awesome, we'll review this soon. Thank you!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In `@packages/core/platform/sources/opensearch-application.yaml`:
- Around line 12-22: The YAML uses 4-space indentation for list items under keys
like variants, dependsOn, libraries, and components (e.g., the "variants" block
with "name: default" and "components: opensearch"); change these list-item
indentations to the 2-space style used in the other source file so list entries
(e.g., - name: default, - cozystack.networking, - name: cozy-lib, - name:
opensearch) are indented with 2 spaces consistently throughout the file.
🧹 Nitpick comments (1)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In `@packages/core/platform/sources/opensearch-application.yaml`:
- Around line 12-22: The YAML uses 4-space indentation for list items under keys
like variants, dependsOn, libraries, and components (e.g., the "variants" block
with "name: default" and "components: opensearch"); change these list-item
indentations to the 2-space style used in the other source file so list entries
(e.g., - name: default, - cozystack.networking, - name: cozy-lib, - name:
opensearch) are indented with 2 spaces consistently throughout the file.
packages/core/platform/sources/opensearch-application.yaml (1)

12-22: Nit: inconsistent YAML indentation style across the two source files.

This file indents list items under variants: with 4 spaces, while opensearch-operator.yaml uses 2 spaces. Both are valid YAML, but aligning on one style improves consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/platform/sources/opensearch-application.yaml` around lines 12 -
22, The YAML uses 4-space indentation for list items under keys like variants,
dependsOn, libraries, and components (e.g., the "variants" block with "name:
default" and "components: opensearch"); change these list-item indentations to
the 2-space style used in the other source file so list entries (e.g., - name:
default, - cozystack.networking, - name: cozy-lib, - name: opensearch) are
indented with 2 spaces consistently throughout the file.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.


In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml`:
- Around line 80-85: The closing brace spacing for the securityContext nindent
call is inconsistent: change the `{{- toYaml .Values.securityContext | nindent
8}}` invocation so it matches the other blocks (use a space before the closing
braces like the `nodeSelector` and `tolerations` lines), i.e., update the
`securityContext` template line referencing `.Values.securityContext` to use
`nindent 8 }}` for consistent formatting.
- Around line 1-94: This change directly edits a vendored upstream Helm chart
(the Deployment template that defines containers kube-rbac-proxy and
operator-controller-manager) which violates the guideline; revert direct
modifications in this vendored chart and instead implement the indentation/fix
changes via a proper chart patch or a post-render hook (or Helm chart overlay)
that targets the opensearch-operator-controller-manager Deployment template
(matching metadata name from the template and container names kube-rbac-proxy /
operator-controller-manager) so the upstream chart can be re-vendored cleanly in
future.
🧹 Nitpick comments (2)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed.


In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml`:
- Around line 80-85: The closing brace spacing for the securityContext nindent
call is inconsistent: change the `{{- toYaml .Values.securityContext | nindent
8}}` invocation so it matches the other blocks (use a space before the closing
braces like the `nodeSelector` and `tolerations` lines), i.e., update the
`securityContext` template line referencing `.Values.securityContext` to use
`nindent 8 }}` for consistent formatting.
- Around line 1-94: This change directly edits a vendored upstream Helm chart
(the Deployment template that defines containers kube-rbac-proxy and
operator-controller-manager) which violates the guideline; revert direct
modifications in this vendored chart and instead implement the indentation/fix
changes via a proper chart patch or a post-render hook (or Helm chart overlay)
that targets the opensearch-operator-controller-manager Deployment template
(matching metadata name from the template and container names kube-rbac-proxy /
operator-controller-manager) so the upstream chart can be re-vendored cleanly in
future.
packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml (2)

80-85: Inconsistent closing brace spacing on line 85.

Line 85 uses nindent 8}} (no space before }}), while all other nindent calls in the file have a space before }} (e.g., nindent 8 }}). While Helm handles both, this is inconsistent with the rest of the template.

Proposed fix
       securityContext:
-{{- toYaml .Values.securityContext | nindent 8}}
+{{- toYaml .Values.securityContext | nindent 8 }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml`
around lines 80 - 85, The closing brace spacing for the securityContext nindent
call is inconsistent: change the `{{- toYaml .Values.securityContext | nindent
8}}` invocation so it matches the other blocks (use a space before the closing
braces like the `nodeSelector` and `tolerations` lines), i.e., update the
`securityContext` template line referencing `.Values.securityContext` to use
`nindent 8 }}` for consistent formatting.

1-94: This file resides in a vendored upstream chart directory and appears to be directly modified.

Per the coding guidelines: "Do NOT directly edit upstream Helm charts in vendored charts directory; use proper chart vendoring mechanisms." The commit messages confirm that indentation fixes and other changes were applied directly to this template. Consider applying these fixes through patch files or a post-render hook instead, so the vendored chart can be cleanly re-vendored when the upstream releases updates.

As per coding guidelines, **/*.yaml: "Do NOT directly edit upstream Helm charts in vendored charts directory; use proper chart vendoring mechanisms."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/system/opensearch-operator/charts/opensearch-operator/templates/opensearch-operator-controller-manager-deployment.yaml`
around lines 1 - 94, This change directly edits a vendored upstream Helm chart
(the Deployment template that defines containers kube-rbac-proxy and
operator-controller-manager) which violates the guideline; revert direct
modifications in this vendored chart and instead implement the indentation/fix
changes via a proper chart patch or a post-render hook (or Helm chart overlay)
that targets the opensearch-operator-controller-manager Deployment template
(matching metadata name from the template and container names kube-rbac-proxy /
operator-controller-manager) so the upstream chart can be re-vendored cleanly in
future.

Matthieu and others added 4 commits February 16, 2026 22:54
Add OpenSearch application with operator and resource definition:
- App chart with multi-version support (v1/v2/v3), TLS, auth, dashboards
- OpenSearch operator wrapper (opster v2.8.0) with sysctl daemonset
- ApplicationDefinition for Cozystack platform integration

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Add operator and application PackageSource CRs to expose OpenSearch
in the Cozystack platform:
- opensearch-operator: operator deployment in cozy-opensearch-operator namespace
- opensearch-application: app + resource definition with cozy-lib integration

This enables OpenSearch to appear in the platform dashboard and be
deployed by tenants.

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Address CodeRabbit review feedback:
- Fix extraEnv indentation (nindent 8 → 10) in controller-manager deployment
- Fix imagePullSecrets indentation (nindent 6 → 8) for proper YAML alignment
- Change proxy-rolebinding from conditional RoleBinding to always ClusterRoleBinding
  (required for cluster-scoped tokenreviews/subjectaccessreviews permissions)
- Pin operator chart version to 2.8.0 in Makefile for reproducible builds

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Address CodeRabbit nitpick feedback:
- Fix inconsistent indentation in opensearch-application.yaml (4 spaces → 2 spaces)
  to match opensearch-operator.yaml style
- Add missing space in controller-manager-deployment.yaml template
  (nindent 8}} → nindent 8 }}) for consistency

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Fix versions.yaml to use unquoted keys for valid YAML mapping, and
use release-based naming for sysctl DaemonSet to avoid conflicts.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Comment thread packages/system/opensearch-operator/templates/sysctl-daemonset.yaml Outdated
Comment thread packages/apps/opensearch/values.yaml
Matthieu and others added 3 commits March 17, 2026 11:20
Remove sysctl DaemonSet in favor of operator's built-in setVMMaxMapCount
init container, fix schema conflicts with required+empty default, fix
update-versions.sh YAML output format, and use $(MAKE) in Makefile.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Signed-off-by: Matthieu <[email protected]>
The required fields in schema are auto-generated by cozyvalues-gen
and must be kept in sync.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Signed-off-by: Matthieu <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Signed-off-by: Matthieu <[email protected]>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks!

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature lgtm This PR has been approved by a maintainer size/XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants