Skip to content

Introduce cozystack-controller - #560

Merged
Andrei Kvapil (kvaps) merged 18 commits into
mainfrom
cozystack-workload-controller
Jan 9, 2025
Merged

Introduce cozystack-controller#560
Andrei Kvapil (kvaps) merged 18 commits into
mainfrom
cozystack-workload-controller

Conversation

@kvaps

@kvaps Andrei Kvapil (kvaps) commented Jan 3, 2025

Copy link
Copy Markdown
Member

for tests deploy redis, then:

kubectl label pod rfr-redis-asdasd-0 rfr-redis-asdasd-1 workload.cozystack.io/kind=redis workload.cozystack.io/type=redis --overwrite
kubectl label pod rfs-redis-asdasd-656c657856-2rsbs rfs-redis-asdasd-656c657856-98stl rfs-redis-asdasd-656c657856-fwldw workload.cozystack.io/kind=redis workload.cozystack.io/type=sentinel

kubectl annotate pod rfs-redis-asdasd-656c657856-2rsbs rfs-redis-asdasd-656c657856-98stl rfs-redis-asdasd-656c657856-fwldw workload.cozystack.io/resources='{"cpu": "200m"}' --overwrite

Summary by CodeRabbit

Based on the comprehensive changes, here are the release notes:

  • New Features

    • Introduced CozyStack Controller for enhanced workload monitoring and management
    • Added telemetry configuration options with ability to disable telemetry
    • Implemented new Custom Resource Definitions (CRDs) for Workload and WorkloadMonitor
  • Improvements

    • Increased CozyStack API deployment replicas from 1 to 2 for improved availability
    • Updated module and import paths for better organization
    • Enhanced configuration management for system components
  • Chores

    • Updated copyright year to 2025
    • Migrated repository references from aenix.io to aenix-io
    • Updated Go version to 1.23
  • Documentation

    • Added comprehensive configuration options for new components

@dosubot dosubot Bot added the size/XXL This PR changes 1000+ lines, ignoring generated files label Jan 3, 2025
@coderabbitai

coderabbitai Bot commented Jan 3, 2025

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

Walkthrough

This pull request introduces significant enhancements to the Cozystack project, focusing on expanding the controller infrastructure, introducing new API resources, and improving telemetry capabilities. The changes include adding a new WorkloadMonitor Custom Resource Definition, implementing a telemetry collection system, updating import paths, and introducing a new Kubernetes controller for managing workload monitoring. The modifications span multiple packages and introduce new configuration options for telemetry and controller management.

Changes

File/Directory Change Summary
Makefile Added new generate target to execute code generation script
api/v1alpha1/ Added new API types for WorkloadMonitor and Workload, including groupversion_info.go, workload_types.go, and workloadmonitor_types.go
cmd/cozystack-controller/main.go New main package for Cozystack controller with telemetry and configuration setup
internal/controller/ Added workloadmonitor_controller.go and suite_test.go for workload monitoring controller
internal/telemetry/ New package with collector.go and config.go for telemetry data collection
packages/system/cozystack-controller/ New Helm chart for Cozystack controller, including deployment, RBAC, and CRD configurations
go.mod Updated module path and dependencies
Import paths Updated from github.com/aenix.io/cozystack to github.com/aenix-io/cozystack across multiple files

Poem

🐰 Hop, hop, controller's might,
Telemetry dancing in the light,
APIs bloom like spring's first flower,
Cozystack grows with coding power!
Monitoring workloads, smooth and neat,
A rabbit's code can't be beat! 🚀


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6567f96 and 836128c.

📒 Files selected for processing (2)
  • internal/controller/workloadmonitor_controller.go (1 hunks)
  • packages/system/cozystack-controller/values.yaml (1 hunks)

Finishing Touches

  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@dosubot dosubot Bot added the kind/feature Categorizes issue or PR as related to a new feature label Jan 3, 2025

@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: 20

🧹 Nitpick comments (50)
packages/system/cozystack-workload-controller/Dockerfile (4)

2-4: Pin the Golang version for reproducible builds.

Using a floating tag (golang:1.22) can lead to inconsistent builds when the underlying image is updated. Consider pinning to a specific patch version.

-FROM golang:1.22 AS builder
+FROM golang:1.22.0 AS builder

15-17: Consider adding a .dockerignore file.

While the COPY commands are specific, adding a .dockerignore file would ensure no unnecessary files (like tests, documentation, or temporary files) are included in the build context.

Example .dockerignore content:

**/*_test.go
**/testdata/
**/*.md
**/.git

24-24: Enhance binary security and optimization with additional build flags.

Consider adding security and optimization flags to the Go build command.

-RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
+RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -trimpath -ldflags="-w -s" -o manager cmd/main.go

The additional flags:

  • -trimpath: Removes file system paths from the binary for better reproducibility
  • -ldflags="-w -s": Reduces binary size by removing debug information

28-33: Consider additional security enhancements.

While the current security setup is good, consider these additional security measures:

-FROM gcr.io/distroless/static:nonroot
+FROM gcr.io/distroless/static:nonroot@sha256:<hash>
 WORKDIR /
 COPY --from=builder /workspace/manager .
 USER 65532:65532
+
+# Add security configurations
+LABEL org.opencontainers.image.source="https://github.com/aenix-io/cozystack"
+LABEL org.opencontainers.image.description="CozyStack Workload Controller"
+
+# Enable additional security options
+SECURITY_OPT ["no-new-privileges:true"]
 
 ENTRYPOINT ["/manager"]

Enhancements:

  1. Pin the distroless image to a specific SHA for better security
  2. Add image metadata labels for transparency
  3. Prevent privilege escalation
packages/system/cozystack-workload-controller/.golangci.yml (2)

5-18: Consider documenting exclusion rules

The configuration explicitly disables default exclusions and adds custom ones, which is good. However, it would be helpful to document why certain linters are excluded for specific paths.

 exclude-rules:
   - path: "api/*"
+    # Exclude line length checks for generated API code
     linters:
       - lll
   - path: "internal/*"
+    # Exclude code duplication and line length checks for internal implementation
     linters:
       - dupl
       - lll

19-43: Consider adding additional Kubernetes-specific linters

The enabled linters provide good coverage for general Go code quality. However, for a Kubernetes controller, consider adding:

  • gosec for security checks
  • exportloopref for detecting pointer issues in loops
  • errname for error naming conventions
 enable:
   - dupl
   - errcheck
   - copyloopvar
   - ginkgolinter
+  - gosec
+  - exportloopref
+  - errname
   - goconst
packages/system/cozystack-workload-controller/go.mod (1)

52-55: Consider configuring Prometheus metrics for the controller

The inclusion of Prometheus client libraries suggests metrics implementation. This is a good practice for Kubernetes controllers. Consider implementing:

  • Reconciliation duration metrics
  • Error count metrics
  • Queue depth metrics

Would you like me to provide an example implementation of controller metrics using the Prometheus client?

packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role.yaml (1)

1-17: LGTM! Role has appropriate permissions for metrics authentication.

The ClusterRole correctly defines the minimum required permissions for metrics authentication:

  • create permission for tokenreviews in the authentication.k8s.io group
  • create permission for subjectaccessreviews in the authorization.k8s.io group

These permissions are necessary for implementing secure metrics collection with authentication.

Consider documenting the metrics authentication flow in the repository's documentation to help future maintainers understand the security model.

packages/system/cozystack-workload-controller/config/rbac/role_binding.yaml (1)

1-15: LGTM! ClusterRoleBinding follows Kubernetes controller patterns.

The configuration correctly binds the cluster-wide permissions to the controller-manager ServiceAccount in the system namespace. The use of ClusterRoleBinding is appropriate for a controller that needs cluster-wide access to manage workloads.

For enhanced security, ensure that the referenced manager-role ClusterRole follows the principle of least privilege and only grants permissions necessary for the workload controller's operations.

packages/system/cozystack-workload-controller/config/rbac/leader_election_role_binding.yaml (1)

1-15: LGTM! RoleBinding properly configured for leader election.

The configuration correctly sets up namespaced permissions for leader election, which is essential for high availability in multi-replica deployments of the workload controller.

Consider documenting the high availability setup in the controller's README, including:

  • How leader election works
  • What happens during failover
  • How to configure the number of replicas
packages/system/cozystack-workload-controller/config/rbac/workload_viewer_role.yaml (1)

1-23: LGTM! Viewer role properly restricts permissions to read-only operations.

The ClusterRole correctly defines read-only access to workload resources and their status subresource within the cozystack.io API group.

Consider these enhancements for better multi-tenant support:

  1. Add namespace selector labels to support multi-tenant isolation
  2. Consider adding the patch verb for the status subresource if monitoring tools or integrations need to update status conditions

Example enhancement:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: workload-viewer-role
  labels:
    app.kubernetes.io/name: cozystack-workload-controller
    app.kubernetes.io/managed-by: kustomize
    # Add tenant isolation label
    tenant.cozystack.io/isolation: "true"
rules:
- apiGroups:
  - cozystack.io
  resources:
  - workloads
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - cozystack.io
  resources:
  - workloads/status
  verbs:
  - get
  - patch  # Add patch for status updates if needed
packages/system/cozystack-workload-controller/config/rbac/leader_election_role.yaml (1)

4-8: Consider adding namespace selector for enhanced security

While the current labels are good for identification, consider adding a namespace selector to further restrict where this Role can be bound:

  labels:
    app.kubernetes.io/name: cozystack-workload-controller
    app.kubernetes.io/managed-by: kustomize
+   cozystack.io/namespace-selector: system
  name: leader-election-role
packages/system/cozystack-workload-controller/config/network-policy/kustomization.yaml (1)

1-2: Consider documenting controller architecture and observability strategy

While the Kustomize configurations are well-structured, consider enhancing the PR with:

  1. Documentation describing the workload controller's architecture, responsibilities, and operational model
  2. Details about the metrics being exposed and recommended monitoring/alerting configurations
  3. Integration testing strategy for the NetworkPolicy to ensure it doesn't interfere with existing monitoring setups

This will help with maintainability and operational readiness.

packages/system/cozystack-workload-controller/config/crd/kustomizeconfig.yaml (1)

11-17: Verify namespace handling strategy

The namespace configuration with create: false implies that the namespace should exist beforehand. This needs to be documented in the deployment prerequisites.

Consider adding deployment prerequisites documentation that clearly states the namespace requirements.

packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml (1)

13-26: Review security implications of metrics access

The NetworkPolicy configuration looks good with proper label-based selection. However, consider the following security aspects:

  1. The policy allows access from any pod in namespaces with metrics: enabled label
  2. Only ingress traffic is restricted, which is appropriate for metrics collection

Consider documenting:

  1. Which components/namespaces should have the metrics: enabled label
  2. The security implications of enabling metrics access
  3. How to verify proper metrics collection setup
packages/system/cozystack-workload-controller/config/crd/kustomization.yaml (1)

13-15: Consider enabling cert-manager for production

For production deployments, it's recommended to enable cert-manager for proper certificate management. This ensures secure communication between components.

packages/system/cozystack-workload-controller/config/manager/manager.yaml (1)

31-50: Implement node affinity for production deployment

The commented node affinity configuration should be implemented to ensure proper scheduling across different architectures.

Uncomment and adjust the node affinity configuration based on your supported platforms:

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/arch
            operator: In
            values:
              - amd64
              - arm64
packages/system/cozystack-workload-controller/config/default/kustomization.yaml (1)

44-177: Document requirements for optional features.

The file includes comprehensive configurations for webhooks, cert-manager, and conversion webhooks, but they're all commented out. Consider documenting:

  1. Whether these features are planned for future implementation
  2. The conditions or milestones that would trigger their enablement
  3. Any dependencies or prerequisites needed before enabling them

Consider adding a comment section at the top of the file documenting the roadmap for these features.

+# Feature Roadmap:
+# - Webhooks: [TODO: Document plans and triggers for enabling webhooks]
+# - Cert-manager: [TODO: Document certificate management strategy]
+# - Conversion Webhooks: [TODO: Document API version conversion requirements]
+
 # Adds namespace to all resources.
 namespace: cozystack-workload-controller-system
packages/system/cozystack-workload-controller/internal/controller/suite_test.go (2)

49-54: Consider augmenting the test coverage.
Adding more test specs and possibly sub-tests for individual controller behaviors (e.g., reconciling CR creation, update, and delete) can help ensure better regression prevention.


55-72: Parameterize the Kubernetes version for maintainability.
Currently, the BinaryAssetsDirectory is hard-coded to Kubernetes 1.31.0. Consider making this version configurable (e.g., via environment variables) to simplify updates and testing across different versions of Kubernetes.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (3)

35-38: Use suitable logging for debugging.

Defining the reconciler struct is correct. However, consider adding explicit debug or trace logs in the fields or constructor to simplify diagnosing potential client or scheme-related initialization issues in the future.


44-113: Consider partial update logic and handle large resource map scenarios.

This method builds a comprehensive resource map for the workload, merging container limits with annotation-based overrides. This can become quite large for pods with many containers or extensive annotations. Consider partial updates or chunked merges if your environment might see pods with very large resource annotations to avoid potential memory spikes or API server overhead.


115-143: Validate the presence of essential labels more robustly.

Here, you rely on checking pod.Labels["workload.cozystack.io/kind"]. Consider verifying pod.Labels is non-nil to safeguard future versions of the K8s API or unexpected states. Also, if you need other labels in the future, centralizing label validation may help.

packages/system/cozystack-workload-controller/cmd/main.go (2)

55-71: Document command-line flags usage.

Flags such as -metrics-secure and -enable-http2 drastically change security and network protocols. Consider adding a small help section or usage statement indicating best practices for each flag, especially in production environments.


80-90: Review vulnerability advisories periodically.

Disabling HTTP/2 by default is prudent given the references to existing CVEs. However, keep this logic updated if future advisories are resolved or if performance or feature requirements mandate enabling HTTP/2.

packages/system/cozystack-workload-controller/test/utils/utils.go (1)

168-178: Evaluate potential error handling for loading images into Kind clusters.

LoadImageToKindClusterWithName relies on environment variables and a shell command. If kind isn't installed or the cluster name is incorrect, it will simply fail. Consider providing more descriptive errors or verifying prerequisites before calling this function.

packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1)

42-42: Provide acceptable resource defaults or mark them as optional.

Resources is flagged as required, but some workloads may not specify CPU/memory on creation. If you anticipate partial or incremental resource declarations, consider making them optional or providing sane defaults to prevent nil pointer issues.

packages/system/cozystack-workload-controller/internal/controller/workload_controller_test.go (2)

45-58: Provide valid spec data for resource creation.

This code snippet creates a Workload with minimal fields. Adding representative Spec fields, if any exist, will help ensure your reconciliation logic is tested in a realistic scenario and can detect any schema or validation issues.


60-68: Defend against concurrent test runs.

This test suite deletes a shared resource in AfterEach. If other attempts reference the same resource concurrently, it might produce unexpected side effects or object not found errors. Ensure each test uses unique resource names or orchestrate concurrency via test framework.

packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (4)

37-38: Consider logging environment variable values before skipping installation

It might be helpful to log the values of PROMETHEUS_INSTALL_SKIP and CERT_MANAGER_INSTALL_SKIP for better clarity during debugging.


63-67: Add a task to verify if code is generated as expected

You’re generating code through make generate, but it might be beneficial to run a validation step to ensure that no changes (e.g., uncommitted diffs) are produced after generating code. This helps ensure code generation processes are deterministic.


78-83: Enhance clarity regarding the environment

A comment states "If you want to change the e2e test vendor from Kind...", but the test code also interacts with local Docker images. Consider clarifying or referencing a doc on how to run these tests on a platform other than Kind for future maintainability.


Line range hint 110-126: Enhance error handling for log fetching tasks

Within AfterEach, the code attempts to fetch logs, events, and describe pods. If these steps fail, the error is only partially logged. Consider additional error context or graceful fallback steps for broader debugging coverage, e.g., partial success for each command.

packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (5)

90-92: Consider narrower failure scope in AfterEach

When a spec fails, you gather logs, but if there’s a single test failure in a large suite, it might produce overwhelming outputs. Consider scoping or grouping logs, or using a more targeted approach.


104-108: Ensure error readability for events retrieval

When kubectl get events fails, the user sees “Failed to get Kubernetes events: X”. For large tests, consider adding more context, e.g., “Ensure the cluster is functioning or that you have cluster permissions.”

🧰 Tools
🪛 golangci-lint (1.62.2)

105-105: printf: non-constant format string in call to fmt.Fprintf

(govet)


133-144: Simplify retrieval logic using label selectors

When searching for the controller-manager pod, you rely on a label plus filtering out resources with a .metadata.deletionTimestamp. Alternatively, you can combine label selectors in the kubectl get pods command to refine the results in a single step.


210-217: Parameterize the curl command or container image

Currently, the code references curlimages/curl:7.78.0 directly. Consider defining constants or environment variables to make the container image version easily configurable.


291-299: Add fallback if logs retrieval fails

In getMetricsOutput(), if the logs retrieval fails, the test fails immediately. Consider a fallback or quick reattempt logic in case of transient issues, e.g., network or container readiness.

packages/system/cozystack-workload-controller/.github/workflows/test.yml (2)

1-1: Align workflow name with standard naming practices

Consider naming your workflow more specifically, e.g., Go Unit Tests or CI Tests, to differentiate from other test pipelines like E2E.


20-23: Add caching for Go modules

Caching your ~/.cache/go-build or ~/go/pkg/mod directories might speed up subsequent CI runs.

      - name: Cache Go modules
        uses: actions/cache@v3
        with:
          path: ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
packages/system/cozystack-workload-controller/.devcontainer/post-install.sh (1)

17-17: Check if network already exists

The script unconditionally creates a kind network. In some environments, that network could already exist. Consider checking first or ignoring errors if it already exists.

packages/system/cozystack-workload-controller/.github/workflows/test-e2e.yml (3)

8-11: Add job timeout and resource limits

Consider adding timeout and resource limits to prevent long-running or resource-intensive jobs from consuming excessive resources:

  test-e2e:
    name: Run on Ubuntu
    runs-on: ubuntu-latest
+   timeout-minutes: 30
+   env:
+     GOMEMLIMIT: 1GiB

15-19: Enable Go modules cache

Add caching for Go modules to speed up the workflow:

      - name: Setup Go
        uses: actions/setup-go@v5
        with:
          go-version: '~1.22'
+         cache: true

29-30: Consider using a kind configuration file

The current setup uses default kind configuration. Consider using a configuration file to specify cluster settings like:

  • Node image version
  • Extra port mappings
  • Resource limits

Would you like me to generate a kind configuration file with recommended settings?

packages/system/cozystack-workload-controller/README.md (3)

48-48: Fix grammar in samples note

Correct the subject-verb agreement:

- >**NOTE**: Ensure that the samples has default values to test it out.
+ >**NOTE**: Ensure that the samples have default values to test them out.
🧰 Tools
🪛 LanguageTool

[grammar] ~48-~48: It looks like you are using the wrong form of the noun or the verb. Did you mean “sample has” or “samples have”?
Context: ...amples/ ``` >NOTE: Ensure that the samples has default values to test it out. ### To ...

(NOUN_PLURAL_HAS)


38-40: Enhance RBAC documentation

Add more detailed information about required RBAC permissions:

 > **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin
-privileges or be logged in as admin.
+privileges or be logged in as admin. The following permissions are required:
+- Create/update/delete Workload CRDs
+- Access to metrics endpoints
+- Permission to create/update ServiceAccounts and Roles

101-101: Update copyright year

The copyright year should be current:

-Copyright 2025.
+Copyright 2024.
packages/system/cozystack-workload-controller/Makefile (3)

66-81: Enhance e2e test automation

The current e2e test setup could be improved by automating the Kind cluster creation and configuration. This would make the testing process more streamlined and reduce manual setup steps.

Consider adding these improvements:

  1. Automatically create a Kind cluster if not present
  2. Add configuration options for the Kind cluster setup (e.g., number of nodes, Kubernetes version)
  3. Add cleanup functionality to tear down the cluster after tests

Example implementation:

 .PHONY: test-e2e
 test-e2e: manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind.
+	@if ! command -v kind >/dev/null 2>&1; then \
+		echo "Installing Kind..."; \
+		go install sigs.k8s.io/kind@latest; \
+	fi
 	@kind get clusters | grep -q 'kind' || { \
-		echo "No Kind cluster is running. Please start a Kind cluster before running the e2e tests."; \
-		exit 1; \
+		echo "Creating Kind cluster..."; \
+		kind create cluster --name cozystack-e2e --config test/e2e/kind-config.yaml; \
 	}
 	go test ./test/e2e/ -v -ginkgo.v
+	@if [ "$(KEEP_CLUSTER)" != "true" ]; then \
+		echo "Cleaning up Kind cluster..."; \
+		kind delete cluster --name cozystack-e2e; \
+	fi

202-212: Enhance tool installation security and reliability

The current tool installation process could benefit from additional security and reliability measures.

Consider these improvements:

  1. Add checksum verification for downloaded binaries
  2. Add cleanup for failed installations
  3. Add timeout for installations
 define go-install-tool
-@[ -f "$(1)-$(3)" ] || { \
+@[ -f "$(1)-$(3)" ] || { \
 set -e; \
+trap 'rm -f $(1)-$(3).tmp' EXIT; \
 package=$(2)@$(3) ;\
 echo "Downloading $${package}" ;\
 rm -f $(1) || true ;\
-GOBIN=$(LOCALBIN) go install $${package} ;\
+GOBIN=$(LOCALBIN) timeout 300s go install $${package} ;\
+if [ -f "$(1)" ]; then \
+  mv $(1) $(1)-$(3).tmp && \
+  # Add checksum verification here if available \
+  mv $(1)-$(3).tmp $(1)-$(3); \
+else \
+  echo "Failed to install $$package" >&2; \
+  exit 1; \
+fi; \
-mv $(1) $(1)-$(3) ;\
 } ;\
 ln -sf $(1)-$(3) $(1)
 endef

93-95: Add version information to the binary

Consider adding version information to the binary during build time. This helps with debugging and support.

 .PHONY: build
 build: manifests generate fmt vet ## Build manager binary.
-	go build -o bin/manager cmd/main.go
+	go build -ldflags "-X main.Version=$$(git describe --tags --always) -X main.BuildTime=$$(date -u +'%Y-%m-%dT%H:%M:%SZ')" -o bin/manager cmd/main.go
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26388c7 and 9f38f3a.

⛔ Files ignored due to path filters (1)
  • packages/system/cozystack-workload-controller/go.sum is excluded by !**/*.sum
📒 Files selected for processing (49)
  • packages/system/cozystack-workload-controller/.devcontainer/devcontainer.json (1 hunks)
  • packages/system/cozystack-workload-controller/.devcontainer/post-install.sh (1 hunks)
  • packages/system/cozystack-workload-controller/.dockerignore (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/lint.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/test-e2e.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/test.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.gitignore (1 hunks)
  • packages/system/cozystack-workload-controller/.golangci.yml (1 hunks)
  • packages/system/cozystack-workload-controller/Dockerfile (1 hunks)
  • packages/system/cozystack-workload-controller/Makefile (1 hunks)
  • packages/system/cozystack-workload-controller/PROJECT (1 hunks)
  • packages/system/cozystack-workload-controller/README.md (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/groupversion_info.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/kustomizeconfig.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/manager_metrics_patch.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/metrics_service.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/manager/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/manager/manager.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/network-policy/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/prometheus/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/leader_election_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/leader_election_role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_reader_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/service_account.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/workload_viewer_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/samples/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/samples/v1alpha1_workload.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/go.mod (1 hunks)
  • packages/system/cozystack-workload-controller/hack/boilerplate.go.txt (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/suite_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/utils/utils.go (1 hunks)
✅ Files skipped from review due to trivial changes (13)
  • packages/system/cozystack-workload-controller/.dockerignore
  • packages/system/cozystack-workload-controller/hack/boilerplate.go.txt
  • packages/system/cozystack-workload-controller/.github/workflows/lint.yml
  • packages/system/cozystack-workload-controller/config/samples/v1alpha1_workload.yaml
  • packages/system/cozystack-workload-controller/config/rbac/service_account.yaml
  • packages/system/cozystack-workload-controller/config/default/metrics_service.yaml
  • packages/system/cozystack-workload-controller/.gitignore
  • packages/system/cozystack-workload-controller/.devcontainer/devcontainer.json
  • packages/system/cozystack-workload-controller/config/samples/kustomization.yaml
  • packages/system/cozystack-workload-controller/api/v1alpha1/groupversion_info.go
  • packages/system/cozystack-workload-controller/config/rbac/kustomization.yaml
  • packages/system/cozystack-workload-controller/PROJECT
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go
🧰 Additional context used
🪛 LanguageTool
packages/system/cozystack-workload-controller/README.md

[grammar] ~48-~48: It looks like you are using the wrong form of the noun or the verb. Did you mean “sample has” or “samples have”?
Context: ...amples/ ``` >NOTE: Ensure that the samples has default values to test it out. ### To ...

(NOUN_PLURAL_HAS)

🪛 Markdownlint (0.37.0)
packages/system/cozystack-workload-controller/README.md

107-107: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)

🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/test/e2e/e2e_test.go

281-281: unnecessary conversion

(unconvert)


96-96: printf: non-constant format string in call to fmt.Fprintf

(govet)


98-98: printf: non-constant format string in call to fmt.Fprintf

(govet)


105-105: printf: non-constant format string in call to fmt.Fprintf

(govet)

packages/system/cozystack-workload-controller/test/utils/utils.go

95-95: unnecessary conversion

(unconvert)


156-156: unnecessary conversion

(unconvert)

🔇 Additional comments (31)
packages/system/cozystack-workload-controller/Dockerfile (2)

6-12: Well-structured dependency caching!

Excellent implementation of Docker layer caching. The separate copying of go.mod/go.sum files and downloading dependencies before copying source code optimizes rebuild times.


28-31: Excellent security practices!

Great implementation of security best practices:

  • Using distroless base image reduces attack surface
  • Running as non-root user enhances security
packages/system/cozystack-workload-controller/.golangci.yml (2)

1-3: LGTM: Run configuration looks good

The timeout of 5 minutes and parallel runners configuration are reasonable defaults for a Kubernetes controller project.


1-47: Verify integration with CI pipeline

Ensure this configuration is properly integrated with your CI pipeline and works with the specified GitHub Actions workflow mentioned in the summary.

✅ Verification successful

Let me gather more information about the CI integration.


Linting configuration is properly integrated with build system

The golangci-lint configuration is well integrated into the build system:

  • The Makefile has proper lint targets (lint and lint-fix) that use golangci-lint
  • The linter is automatically installed if not present via the golangci-lint target
  • The referenced paths in the configuration (api/* and internal/*) exist in the project structure
  • The configuration applies to the correct package (packages/system/cozystack-workload-controller)

While there's no dedicated GitHub Actions workflow file for linting visible in the results, the Makefile integration ensures that linting can be run locally and can be easily integrated into any CI pipeline by calling the make targets.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify golangci-lint configuration integration

# Check for GitHub Actions workflow file
echo "Checking for lint workflow file..."
fd -t f "lint.yml" .github/workflows/

# Verify Makefile integration
echo "Checking for golangci-lint in Makefile..."
rg "golangci-lint" Makefile

# Check if all referenced paths exist
echo "Verifying referenced paths..."
fd -t d "api" .
fd -t d "internal" .

Length of output: 1003


Script:

#!/bin/bash
# Check for GitHub Actions workflow files that might run linting
echo "Checking all workflow files for golangci-lint usage..."
fd -t f "\.ya?ml$" .github/workflows/ -x cat {} \; | grep -A 5 -B 5 "golangci-lint"

# Check for any make targets related to linting
echo "Checking Makefile for lint targets..."
fd Makefile -x cat {} \; | grep -A 5 -B 5 "lint"

# Check if golangci-lint is mentioned in any other configuration files
echo "Checking other potential configuration files..."
rg -g "!.golangci.yml" "golangci-lint" .

Length of output: 3296

packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml (1)

2-4: Consider namespace-scoped Role instead of ClusterRole for better security.

The use of ClusterRole grants permissions across all namespaces. Unless cross-namespace workload management is explicitly required, consider using a namespace-scoped Role to follow the principle of least privilege.

Let's verify if workloads are intended to be namespace-scoped:

packages/system/cozystack-workload-controller/go.mod (3)

60-67: Good practice: OpenTelemetry integration for observability

The inclusion of OpenTelemetry dependencies is a great choice for modern observability. This will allow:

  • Distributed tracing of reconciliation loops
  • Integration with various backend systems
  • Better debugging capabilities

5-11: Verify Kubernetes client-go and controller-runtime version compatibility

The direct dependencies show:

  • k8s.io/client-go v0.31.0
  • k8s.io/apimachinery v0.31.0
  • sigs.k8s.io/controller-runtime v0.19.1

These versions look aligned, but let's verify the compatibility matrix.

✅ Verification successful

Let me verify the compatibility between the versions by checking the controller-runtime's version compatibility matrix.


✅ Kubernetes client-go and controller-runtime versions are compatible

The versions used in the workload controller are properly aligned:

  • controller-runtime v0.19.1 is designed to work with Kubernetes v1.31.x components
  • All Kubernetes components (client-go, apimachinery, api, etc.) are consistently using v0.31.0
  • The dependencies are properly aligned within the module

Note: While there's a different version (v0.31.2) in the root go.mod, this is not a concern as the workload controller is a separate module with its own dependency management.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for version compatibility documentation
echo "Searching for version compatibility documentation..."
fd README.md . -x grep -A 5 -i "compatibility"

# Check if there are any other controllers in the codebase using different versions
echo "Checking for version consistency across controllers..."
rg "k8s.io/client-go" -g "go.mod"

Length of output: 11759


Script:

#!/bin/bash
# Check controller-runtime's go.mod for version compatibility
echo "Checking controller-runtime's dependencies..."
rg "k8s.io/(api|apimachinery|client-go)" -g "go.mod" -A 2

# Check for any version-related issues or warnings in the codebase
echo "Checking for version-related issues..."
rg "controller-runtime.*v0.19" -g "*.go"

Length of output: 2351


87-93: Verify RBAC compatibility with Kubernetes version

The Kubernetes API version (v0.31.0) indicates this is targeting a recent Kubernetes release. Ensure your RBAC manifests are compatible with this version.

✅ Verification successful

RBAC compatibility verified with Kubernetes v0.31.0

All RBAC manifests in the workload controller are using the stable rbac.authorization.k8s.io/v1 API version, which is fully compatible with Kubernetes v0.31.0. No deprecated alpha/beta RBAC API versions were found in the codebase. The RBAC configuration is properly aligned with the target Kubernetes version.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for RBAC manifests and their apiVersions
echo "Checking RBAC manifests..."
fd -e yaml -e yml . config/ -x grep -l "rbac.authorization.k8s.io"

Length of output: 224


Script:

#!/bin/bash
# Search for RBAC manifests and their apiVersions in the entire repository
echo "Checking RBAC manifests..."
fd -e yaml -e yml . -x grep -l "rbac.authorization.k8s.io"

# Also check for any RBAC-related Go code that might define RBAC rules
echo -e "\nChecking RBAC-related code..."
rg -l "rbac.authorization.k8s.io"

# Look for any Kubernetes manifest files
echo -e "\nChecking all Kubernetes manifests..."
fd -e yaml -e yml .

Length of output: 90515


Script:

#!/bin/bash
# Check the apiVersion in RBAC manifests under the workload controller
echo "Checking RBAC apiVersions in workload controller..."
rg "apiVersion.*rbac.authorization.k8s.io" packages/system/cozystack-workload-controller/config/rbac/

# Check if there are any deprecated RBAC apiVersions
echo -e "\nChecking for deprecated RBAC apiVersions..."
rg "apiVersion.*rbac.authorization.k8s.io/v1(alpha|beta)" 

Length of output: 1489

packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role_binding.yaml (1)

1-12: LGTM! Binding is properly configured.

The ClusterRoleBinding correctly associates the metrics-auth-role with the controller-manager ServiceAccount in the system namespace.

Let's verify the existence of the referenced ServiceAccount:

✅ Verification successful

ServiceAccount reference is valid and properly defined

The ClusterRoleBinding correctly references the ServiceAccount controller-manager which is defined in config/rbac/service_account.yaml with matching name and namespace (system). The configuration is consistent and follows Kubernetes best practices.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the ServiceAccount is defined in the repository
rg -l "kind:\s+ServiceAccount.*\n.*name:\s+controller-manager" packages/system/cozystack-workload-controller/

Length of output: 303


Script:

#!/bin/bash
# Check if the ServiceAccount is defined in the repository using multiline mode
rg -U -l "kind:\s+ServiceAccount.*name:\s+controller-manager" packages/system/cozystack-workload-controller/

Length of output: 110


Script:

#!/bin/bash
# Alternative search using ast-grep for YAML
ast-grep --pattern 'kind: ServiceAccount
  name: controller-manager'

Length of output: 70


Script:

#!/bin/bash
# List all YAML files that might contain ServiceAccount definitions
fd -e yaml . packages/system/cozystack-workload-controller/ -x grep -l "ServiceAccount" {}

Length of output: 428


Script:

#!/bin/bash
# Check the content of service_account.yaml
cat packages/system/cozystack-workload-controller/config/rbac/service_account.yaml

Length of output: 289

packages/system/cozystack-workload-controller/config/rbac/role.yaml (2)

7-14: LGTM: Pod permissions follow least privilege principle

The read-only permissions (get, list, watch) for pods are appropriate for a workload controller that needs to monitor pod states without modifying them directly.


15-34: Verify CRD existence for workloads.cozystack.io

The permissions are well-structured for the custom resource. Let's verify the CRD exists:

✅ Verification successful

CRD exists and permissions are correctly configured

The CRD for workloads.cozystack.io exists at packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml and the RBAC permissions in the role.yaml match the controller's requirements:

  • The controller has kubebuilder RBAC markers requesting these exact permissions:
// +kubebuilder:rbac:groups=cozystack.io,resources=workloads,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=cozystack.io,resources=workloads/status,verbs=get;update;patch
  • The role.yaml grants these same permissions:
- apiGroups: ["cozystack.io"]
  resources: ["workloads"]
  verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
- apiGroups: ["cozystack.io"]
  resources: ["workloads/status"] 
  verbs: ["get", "patch", "update"]

The controller is properly integrated with the workload CRD and has the correct RBAC configuration to manage workload resources.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for the workloads CRD definition
# Expected: Should find a CRD definition for workloads.cozystack.io

# Look for CRD definition files
fd -e yaml -e yml | xargs grep -l "kind: CustomResourceDefinition" | xargs grep -l "workloads.cozystack.io"

# Look for references to the API group
rg "cozystack.io" -A 5 -B 5

Length of output: 70250

packages/system/cozystack-workload-controller/config/rbac/leader_election_role.yaml (2)

1-21: LGTM: ConfigMap permissions are appropriate for leader election

The full CRUD permissions on ConfigMaps are correctly scoped as a namespaced Role and are necessary for the leader election mechanism.


22-33: LGTM: Lease permissions follow standard leader election pattern

The permissions on coordination.k8s.io/leases follow the standard Kubernetes leader election pattern used by controllers.

packages/system/cozystack-workload-controller/config/prometheus/kustomization.yaml (1)

1-2: Verify referenced monitor.yaml exists

The configuration looks good and follows Kustomize best practices. Let's verify the existence of the referenced file.

✅ Verification successful

Referenced monitor.yaml exists and is correctly placed

The verification confirms that the referenced monitor.yaml file exists at the expected location: packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml. The kustomization configuration is valid and properly structured.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of monitor.yaml in the same directory
fd --type f --full-path "packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml"

Length of output: 179

packages/system/cozystack-workload-controller/config/manager/kustomization.yaml (1)

1-2: Verify referenced manager.yaml exists

The configuration looks good and follows Kustomize best practices. Let's verify the existence of the referenced file.

✅ Verification successful

Referenced manager.yaml exists and is correctly placed

The verification confirms that the referenced manager.yaml exists at the expected path packages/system/cozystack-workload-controller/config/manager/manager.yaml, validating the kustomization configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of manager.yaml in the same directory
fd --type f --full-path "packages/system/cozystack-workload-controller/config/manager/manager.yaml"

Length of output: 173

packages/system/cozystack-workload-controller/config/network-policy/kustomization.yaml (1)

1-2: Verify NetworkPolicy configuration

The configuration looks good and follows Kustomize best practices. Let's verify:

  1. The existence of the referenced file
  2. The NetworkPolicy configuration aligns with security best practices
✅ Verification successful

NetworkPolicy configuration is properly defined and secure

The NetworkPolicy configuration in allow-metrics-traffic.yaml follows security best practices:

  • Properly restricts ingress traffic to port 8443
  • Only allows access from namespaces labeled with metrics: enabled
  • Correctly targets pods with label control-plane: controller-manager
  • Follows the same pattern as other NetworkPolicies in the system packages
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence and content of the NetworkPolicy
echo "Checking for allow-metrics-traffic.yaml..."
fd --type f --full-path "packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml"

echo "Analyzing NetworkPolicy configuration..."
# Check if the NetworkPolicy properly restricts access to metrics endpoint
rg -A 10 "kind: NetworkPolicy" "packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml"

Length of output: 799


Script:

#!/bin/bash
# Let's check the complete NetworkPolicy configuration to verify ingress rules
rg -A 20 'kind: NetworkPolicy' "packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml"

# Also check if there are any other NetworkPolicy files in the project for comparison
fd --type f --extension yaml --exec rg --type yaml -l "kind: NetworkPolicy" {} \;

Length of output: 2190

packages/system/cozystack-workload-controller/config/crd/kustomizeconfig.yaml (1)

2-10: Verify conversion webhook configuration

The configuration suggests the use of a conversion webhook. This is a critical component that needs proper setup.

packages/system/cozystack-workload-controller/config/crd/kustomization.yaml (1)

4-5: Verify CRD file existence

Please ensure that the referenced CRD file bases/cozystack.io_workloads.yaml exists in the correct location.

✅ Verification successful

CRD file exists at the expected location

The referenced CRD file bases/cozystack.io_workloads.yaml exists at the correct relative path within the package directory, confirming that the kustomization configuration is valid.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the CRD file exists
fd "cozystack.io_workloads.yaml" --type f

Length of output: 132

packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml (1)

13-16: Verify metrics port configuration

Ensure that the port name "https" matches the service port name in your Service definition.

✅ Verification successful

Port configuration is correctly aligned

The port name "https" in the ServiceMonitor configuration matches the service port name in the metrics service definition. The service exposes port 8443 with the name "https", which aligns with the ServiceMonitor's port reference.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check service configuration for metrics port
rg -l "port.*https.*metrics" --type yaml

Length of output: 304


Script:

#!/bin/bash
# Let's check the actual content of the service definition to verify the port configuration
rg "port:.*https" -A 5 -B 5 packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml

Length of output: 624


Script:

#!/bin/bash
# Let's check the service definition in the same directory to verify port name configuration
rg "ports:" -A 5 -B 5 packages/system/cozystack-workload-controller/config/default/manager_service.yaml

Length of output: 225


Script:

#!/bin/bash
# Let's find the service definition file first
fd "service" packages/system/cozystack-workload-controller/config/

Length of output: 227


Script:

#!/bin/bash
# Let's check the metrics service definition
cat packages/system/cozystack-workload-controller/config/default/metrics_service.yaml

Length of output: 474

packages/system/cozystack-workload-controller/config/manager/manager.yaml (1)

85-93: Review resource limits for production workload

The current resource limits might need adjustment based on actual usage patterns:

  • CPU limit (500m) might be restrictive for concurrent workload processing
  • Memory limit (128Mi) might be low for handling multiple workloads

Consider monitoring resource usage in a test environment to determine appropriate limits:

✅ Verification successful

Let me gather more information about resource usage patterns by checking configuration files and any related test files.


Let me gather more specific information about resource usage in similar controllers and workload managers.


Based on the search results, I can now provide a final assessment of the resource limits. Looking at similar controllers in the codebase, particularly the victoria-metrics-operator and other system controllers, I notice that the current resource limits are relatively conservative but reasonable for a controller workload.

Resource limits appear appropriate for the workload controller

The current resource configuration:

  • CPU limit of 500m is in line with other controllers (e.g., victoria-metrics-operator uses same 500m CPU limit)
  • Memory limit of 128Mi is appropriate for a controller that manages workload resources (similar to redis-operator's 128Mi)
  • Request values (10m CPU, 64Mi memory) provide good room for scaling

The configuration follows the common pattern seen across other controllers in the system, balancing resource availability with operational headroom. The relatively low CPU request (10m) allows for efficient scheduling while the limit (500m) provides sufficient capacity for concurrent operations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any existing resource usage patterns in docs or tests
rg -A 5 "resource.*usage|memory.*consumption|cpu.*utilization" --type md

Length of output: 3973


Script:

#!/bin/bash
# Search for similar resource configurations in other controller deployments
rg -A 10 "resources:.*\n.*limits:|requests:" --type yaml

# Look for any test files related to resource usage
fd -e yaml test controller | xargs rg -A 5 "resources:|limits:|requests:"

Length of output: 114419


Script:

#!/bin/bash
# Search for resource configurations in other controller deployments
rg -A 5 "resources:.*\n.*limits:|requests:" --type yaml --multiline

# Look for any workload-related configurations
fd -e yaml -e yml | xargs rg -A 5 "workload.*controller.*resources|controller.*manager.*resources"

Length of output: 75274

packages/system/cozystack-workload-controller/config/default/kustomization.yaml (2)

37-43: Verify metrics configuration and patch file.

The metrics endpoint is configured to use HTTPS on port 8443, which is good security practice. However, we should verify the referenced patch file exists and is properly configured.

✅ Verification successful

Metrics configuration is properly set up with HTTPS

The verification confirms that:

  • The patch file manager_metrics_patch.yaml exists in the correct location
  • The patch correctly configures the metrics endpoint to use port 8443
  • The configuration is consistent with the kustomization reference
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify metrics configuration
# Check if the patch file exists and validate its content

# Check if the patch file exists
test -f packages/system/cozystack-workload-controller/config/default/manager_metrics_patch.yaml || echo "Patch file missing"

# Check patch file content
if [ -f packages/system/cozystack-workload-controller/config/default/manager_metrics_patch.yaml ]; then
  echo "Patch file content:"
  cat packages/system/cozystack-workload-controller/config/default/manager_metrics_patch.yaml
fi

# Check for consistent metrics configuration across other controllers
fd manager_metrics_patch.yaml packages/system

Length of output: 651


1-9: Verify alignment with CozyStack naming conventions.

The namespace and namePrefix look well-structured, but let's ensure they align with CozyStack's established naming patterns.

✅ Verification successful

Naming convention alignment confirmed

Based on the search results, the namespace and namePrefix in cozystack-workload-controller follow the established patterns in the CozyStack ecosystem:

  • System components use the -system suffix for namespaces (e.g., cozy-system, etcd-system, kamaji-system)
  • Controller-specific namespaces follow the pattern {controller-name}-system (e.g., etcd-operator-system, kamaji-system)
  • The current namespace cozystack-workload-controller-system and namePrefix cozystack-workload-controller- are consistent with these patterns
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent naming patterns across CozyStack controllers
# Look for other controller configurations to verify naming consistency

# Search for other kustomization files in system packages
fd kustomization.yaml packages/system -x grep -l "namespace:\|namePrefix:"

# Search for namespace definitions across the codebase
rg "namespace: .*-system$" packages/system

Length of output: 3908

packages/system/cozystack-workload-controller/internal/controller/suite_test.go (3)

1-15: License header looks good.


74-89: Initialization flow is well-structured.
The initialization and scheme registration logic is straightforward and follows envtest best practices.


91-96: Teardown sequence is properly handled.
Canceling the context and stopping the test environment ensures resources are released appropriately.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1)

145-154: Align Owns(&cozyv1alpha1.Workload{}) with your ownership model.

Your call to Owns(&cozyv1alpha1.Workload{}) indicates the Pod is the parent resource in the ownership chain, whereas typically the custom resource (Workload) would own the Pod. Ensure this ownership model matches your intended design, as reversing these roles can lead to confusion about who controls which lifecycle.

packages/system/cozystack-workload-controller/cmd/main.go (1)

121-139: Evaluate graceful shutdown logic before enabling LeaderElectionReleaseOnCancel.

LeaderElectionReleaseOnCancel speeds up leadership transitions but can introduce race conditions if the manager performs cleanup tasks after shutting down. Thoroughly verify if you require final operations post-manager shutdown before enabling.

packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1)

69-71: Confirm CRD registration order is correct.

Ensure the Workload types are added to the scheme before the controller references them. Since you’ve placed SchemeBuilder.Register in func init(), this should be fine, but verify during integration tests that the CRD is found in the cluster when the controller starts.

packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (1)

94-106: Validate format string usage in fmt.Fprintf

The calls at lines 94, 98, 105 use non-constant format strings. Ensure that the fmt.Fprintf usage is safe and does not risk format string vulnerabilities. You could either do:

_, _ = fmt.Fprintf(GinkgoWriter, "WARNING: %s\n", yourStringVar)

or ensure the string variable does not embed format tokens accidentally.

✅ Verification successful

Let me verify the format string usage by searching through the codebase.


Let me check the utils package with a different approach.


Format strings are used safely in this codebase

After analyzing the codebase's fmt.Fprintf usage patterns, I can confirm that the format strings in the specified lines are safe because:

  1. They are constant string literals without any format verbs (%s, %v, etc.)
  2. This pattern is consistent with other logging in the codebase, where format verbs are only used when actually formatting values (as seen in utils.go with "warning: %v\n")
  3. The strings are used for simple logging to GinkgoWriter in a test context

The original concern about format string vulnerabilities doesn't apply here since these are hardcoded messages without any string interpolation or user input.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for the specific file and show the context
rg -U "fmt\.Fprintf.*WARNING:" "packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go"

Length of output: 331


Script:

#!/bin/bash
# Look for similar patterns in other files to understand the convention
rg -U "fmt\.Fprintf.*WARNING:" --type go

Length of output: 414


Script:

#!/bin/bash
# Check if there are any format string vulnerabilities reported or fixed in the git history
git log --grep="fmt.*vulnerability" --grep="format.*string" -i

Length of output: 0


Script:

#!/bin/bash
# Check the utils package to understand how these installations are implemented
fd "utils.*\.go" packages/system/cozystack-workload-controller/test/e2e/ --type f --exec cat {}

Length of output: 99


Script:

#!/bin/bash
# Find the utils package location using a broader search
fd "utils" packages/system/cozystack-workload-controller/ --type d

# Then look for all go files in the test directory that might contain these utilities
fd "\.go$" packages/system/cozystack-workload-controller/test --type f

Length of output: 403


Script:

#!/bin/bash
# Search for other fmt.Fprintf usages in the test files to understand the pattern
rg "fmt\.Fprintf" packages/system/cozystack-workload-controller/test --type go -A 2 -B 2

Length of output: 7343

packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (1)

253-289: Static analysis: "unnecessary conversion" at line 281

For this portion:

var token tokenRequest
err = json.Unmarshal([]byte(output), &token)

The cast to []byte(output) might be unnecessary if output is already of type []byte. Double-check the type of output. If it’s already []byte, you can remove the conversion.

🧰 Tools
🪛 golangci-lint (1.62.2)

281-281: unnecessary conversion

(unconvert)

packages/system/cozystack-workload-controller/.devcontainer/post-install.sh (1)

4-7: Verify correctness of "latest" references

Using kind.sigs.k8s.io/dl/latest/... might break unexpectedly if a future "latest" release introduces breaking changes. Pin these tools to known stable versions to mitigate disruptions.

Comment on lines +44 to +47
linters-settings:
revive:
rules:
- name: comment-spacings

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

Fix incomplete linter settings configuration

The revive rule configuration appears to be incomplete, as it ends abruptly after the rule name.

Complete the configuration by adding the required settings:

 revive:
   rules:
     - name: comment-spacings
+      arguments:
+        - always
+      severity: warning
📝 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
linters-settings:
revive:
rules:
- name: comment-spacings
linters-settings:
revive:
rules:
- name: comment-spacings
arguments:
- always
severity: warning

Comment on lines +9 to +21
rules:
- apiGroups:
- cozystack.io
resources:
- workloads
verbs:
- create
- delete
- get
- list
- patch
- update
- watch

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.

🛠️ Refactor suggestion

Add permissions for finalizers to ensure proper cleanup.

The current set of permissions might not be sufficient for proper resource cleanup. Consider adding permissions for finalizers:

  verbs:
  - create
  - delete
  - get
  - list
  - patch
  - update
  - watch
+ - deletecollection
+ resources:
+ - workloads/finalizers

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +22 to +27
- apiGroups:
- cozystack.io
resources:
- workloads/status
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.

💡 Codebase verification

Add patch/update permissions for status subresource

Based on the code inspection, the workload controller does update the status subresource. This is evident in workload_controller.go where it sets various status fields:

workload.Status.Kind = kind
workload.Status.Type = workloadType
workload.Status.Resources = resources

The current RBAC configuration only allows get on the status subresource, which is insufficient. The controller needs to be able to update these status fields.

  • Add the following verbs to the status subresource permissions in packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml:
    - patch
    - update
🔗 Analysis chain

Review status subresource permissions.

The current configuration only allows reading the status subresource. If workload controllers or operators need to update status conditions, consider adding patch/update permissions:

Let's verify if the workload controller needs to update status:


Let me try another search to specifically look for status updates in the workload controller:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the controller updates status
ast-grep --pattern 'Status {
  $$$
  Conditions $_
  $$$
}'

# Check for status update calls in the controller
rg -A 2 'UpdateStatus|Status\(\).*Patch'

Length of output: 5257


Script:

#!/bin/bash
# Look for status updates in the workload controller implementation
rg -A 3 'Status|conditions?' packages/system/cozystack-workload-controller/

# Check for reconciler patterns that typically update status
ast-grep --pattern 'func (r *$_Reconciler) Reconcile($_) {
  $$$
}'

Length of output: 5870

Comment on lines +1 to +3
module github.com/aenix-io/cozystack

go 1.22.0

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.

💡 Codebase verification

Go version mismatch detected between modules

The workload controller module uses Go 1.22.0, while the root module uses Go 1.23.0. This inconsistency could lead to compatibility issues. You should:

  • Update packages/system/cozystack-workload-controller/go.mod to use Go 1.23.0 to maintain consistency with the root module
  • Note that Go 1.23.0 is still in development (as of January 2025), so consider using a stable version like 1.22.x for both modules
🔗 Analysis chain

Verify Go version compatibility with your CI/CD pipeline

The module uses Go 1.22.0, which was released very recently. While using the latest version is generally good for security and performance, ensure your CI/CD pipeline and deployment environments support this version.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for Go version requirements in GitHub workflows
echo "Checking Go version specifications in GitHub workflows..."
fd -e yml -e yaml . .github/workflows/ -x grep -l "go-version"

Length of output: 187


Script:

#!/bin/bash
# Let's check for any GitHub workflow files first
echo "Looking for GitHub workflow files..."
fd -e yml -e yaml . .github/workflows/

# Also check for any other CI configuration files that might specify Go version
echo -e "\nChecking for other CI config files..."
fd -g "*ci*" -g "*workflow*" -g "*.github*" -g "*build*" .

# Check if there are other Go modules in the repository
echo -e "\nChecking for other Go modules..."
fd "go.mod"

Length of output: 3243


Script:

#!/bin/bash
# Let's check the content of pre-commit.yml to see if it specifies Go version
echo "Checking pre-commit.yml for Go version specifications..."
cat .github/workflows/pre-commit.yml

# Let's also check the root go.mod to see what Go version is used there
echo -e "\nChecking root go.mod..."
cat go.mod

Length of output: 6892

Comment on lines +1 to +9
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: 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.

💡 Codebase verification

⚠️ Security concern: Metrics endpoint uses insecure TLS configuration

While the ClusterRole configuration is correct, the ServiceMonitor configuration reveals a security issue:

  • The metrics endpoint is configured with insecureSkipVerify: true, which disables certificate verification
  • This poses a risk of man-in-the-middle attacks on metrics collection
  • The TODO comment acknowledges this is not recommended for production

Action items:

  • Replace insecureSkipVerify: true with proper TLS configuration using:
    • caFile: /etc/metrics-certs/ca.crt
    • certFile: /etc/metrics-certs/tls.crt
    • keyFile: /etc/metrics-certs/tls.key
🔗 Analysis chain

LGTM! Role follows security best practices.

The ClusterRole configuration follows the principle of least privilege by:

  • Only allowing the get verb
  • Restricting access to just the /metrics endpoint
  • Using nonResourceURLs which is the correct approach for metrics endpoints

Let's verify if this metrics endpoint is properly secured:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there's a corresponding ServiceMonitor or PodMonitor that uses this role
rg -l "kind:\s+(Service|Pod)Monitor" packages/system/cozystack-workload-controller/

Length of output: 162


Script:

#!/bin/bash
# Let's check the content of the monitor.yaml to verify the configuration
cat packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml

Length of output: 1470

Comment on lines +82 to +84
served: true
storage: true
subresources: {}

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.

🛠️ Refactor suggestion

Enable status and scale subresources

Enable status subresource for proper status updates and scale subresource for HPA support:

    served: true
    storage: true
-   subresources: {}
+   subresources:
+     status: {}
+     scale:
+       specReplicasPath: .spec.replicas
+       statusReplicasPath: .status.replicas
+       labelSelectorPath: .status.selector
📝 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
served: true
storage: true
subresources: {}
served: true
storage: true
subresources:
status: {}
scale:
specReplicasPath: .spec.replicas
statusReplicasPath: .status.replicas
labelSelectorPath: .status.selector

Comment on lines +52 to +54
spec:
description: WorkloadSpec defines the desired state of Workload
type: object

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

Spec section requires proper schema definition

The spec section is currently empty. Consider defining the expected fields and their validation rules:

          spec:
            description: WorkloadSpec defines the desired state of Workload
+           properties:
+             replicas:
+               type: integer
+               minimum: 0
+               description: Number of desired replicas
+             resources:
+               type: object
+               properties:
+                 limits:
+                   type: object
+                   additionalProperties:
+                     anyOf:
+                     - type: integer
+                     - type: string
+                     pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                     x-kubernetes-int-or-string: true
+                 requests:
+                   type: object
+                   additionalProperties:
+                     anyOf:
+                     - type: integer
+                     - type: string
+                     pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                     x-kubernetes-int-or-string: true
            type: object
📝 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
spec:
description: WorkloadSpec defines the desired state of Workload
type: object
spec:
description: WorkloadSpec defines the desired state of Workload
properties:
replicas:
type: integer
minimum: 0
description: Number of desired replicas
resources:
type: object
properties:
limits:
type: object
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
requests:
type: object
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
type: object

Comment on lines +1 to +6
# cozystack-workload-controller
// TODO(user): Add simple overview of use/purpose

## Description
// TODO(user): An in-depth paragraph about your project and overview of use

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.

🛠️ Refactor suggestion

Add project overview and description

The TODO placeholders for overview and description should be filled with actual content explaining:

  • Purpose of the workload controller
  • Key features and benefits
  • Target use cases

# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.31.0

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

Fix incorrect Kubernetes version

The specified version 1.31.0 is not a valid Kubernetes version. Kubernetes versions follow semantic versioning with major.minor.patch format (e.g., 1.28.0, 1.29.0).

Please update to a valid Kubernetes version:

-ENVTEST_K8S_VERSION = 1.31.0
+ENVTEST_K8S_VERSION = 1.29.0
📝 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
ENVTEST_K8S_VERSION = 1.31.0
ENVTEST_K8S_VERSION = 1.29.0

Comment on lines +120 to +127
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name cozystack-workload-controller-builder
$(CONTAINER_TOOL) buildx use cozystack-workload-controller-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm cozystack-workload-controller-builder
rm Dockerfile.cross

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.

🛠️ Refactor suggestion

Improve docker-buildx robustness

The current docker-buildx implementation has potential issues with error handling and concurrent builds.

Consider these improvements:

  1. Add proper error handling for buildx commands
  2. Use a unique temporary file for Dockerfile.cross
  3. Ensure cleanup in case of failures
 .PHONY: docker-buildx
 docker-buildx: ## Build and push docker image for the manager for cross-platform support
+	@set -e; \
+	TEMP_DOCKERFILE=$$(mktemp -t Dockerfile.cross.XXXXXX); \
+	trap 'rm -f $$TEMP_DOCKERFILE' EXIT; \
 	# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
-	sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
-	- $(CONTAINER_TOOL) buildx create --name cozystack-workload-controller-builder
+	sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > $$TEMP_DOCKERFILE; \
+	$(CONTAINER_TOOL) buildx create --name cozystack-workload-controller-builder || true; \
 	$(CONTAINER_TOOL) buildx use cozystack-workload-controller-builder
-	- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
-	- $(CONTAINER_TOOL) buildx rm cozystack-workload-controller-builder
-	rm Dockerfile.cross
+	$(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f $$TEMP_DOCKERFILE .; \
+	$(CONTAINER_TOOL) buildx rm cozystack-workload-controller-builder || true
📝 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
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name cozystack-workload-controller-builder
$(CONTAINER_TOOL) buildx use cozystack-workload-controller-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm cozystack-workload-controller-builder
rm Dockerfile.cross
docker-buildx: ## Build and push docker image for the manager for cross-platform support
@set -e; \
TEMP_DOCKERFILE=$$(mktemp -t Dockerfile.cross.XXXXXX); \
trap 'rm -f $$TEMP_DOCKERFILE' EXIT; \
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > $$TEMP_DOCKERFILE; \
$(CONTAINER_TOOL) buildx create --name cozystack-workload-controller-builder || true; \
$(CONTAINER_TOOL) buildx use cozystack-workload-controller-builder
$(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f $$TEMP_DOCKERFILE .; \
$(CONTAINER_TOOL) buildx rm cozystack-workload-controller-builder || true

@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: 21

🧹 Nitpick comments (36)
packages/system/cozystack-workload-controller/config/rbac/metrics_reader_role.yaml (1)

3-4: Consider adding labels and annotations for better resource management.

Adding standard labels and annotations would improve resource management and documentation:

 metadata:
   name: metrics-reader
+  labels:
+    app.kubernetes.io/name: cozystack-workload-controller
+    app.kubernetes.io/component: metrics
+  annotations:
+    description: "Allows reading metrics endpoints for monitoring"
packages/system/cozystack-workload-controller/config/rbac/kustomization.yaml (1)

21-26: Consider additional security measures for CRD roles

While the editor and viewer roles are helpful defaults, consider these security enhancements:

  1. Add namespace-scoped variants of these roles for multi-tenant scenarios
  2. Consider implementing a more granular permission model if different operations need different access levels

Would you like me to provide example YAML configurations for these security enhancements?

packages/system/cozystack-workload-controller/.golangci.yml (1)

9-10: Document which default rules are being restored.

The comment indicates restoring some defaults but doesn't specify which ones. This makes it harder for other developers to understand the intended configuration.

Consider replacing the comment with explicit documentation of which default rules are being restored:

-  # restore some of the defaults
-  # (fill in the rest as needed)
+  # Restoring default rules:
+  # - rule1: description
+  # - rule2: description
packages/system/cozystack-workload-controller/.devcontainer/devcontainer.json (2)

16-19: Consider additional helpful VSCode extensions

While the current extensions cover basic Kubernetes and Docker functionality, consider adding these helpful extensions for enhanced development experience:

  • golang.go for Go language support
  • streetsidesoftware.code-spell-checker for spell checking
  • redhat.vscode-yaml for YAML support (crucial for Kubernetes manifests)

23-23: Improve post-install script execution

The current post-install script execution could be more robust:

  1. Add error handling
  2. Verify script existence
  3. Consider using absolute path
-  "onCreateCommand": "bash .devcontainer/post-install.sh"
+  "onCreateCommand": "if [ -f .devcontainer/post-install.sh ]; then bash .devcontainer/post-install.sh || exit 1; else echo 'Post-install script not found'; exit 1; fi"
packages/system/cozystack-workload-controller/.devcontainer/post-install.sh (3)

8-10: Add version pinning for kubebuilder

Using 'latest' without version pinning could lead to reproducibility issues and unexpected breaking changes.

-curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64
+KUBEBUILDER_VERSION="v3.11.1"  # Replace with your desired version
+curl -L -o kubebuilder "https://go.kubebuilder.io/dl/${KUBEBUILDER_VERSION}/linux/amd64"
 chmod +x kubebuilder
 mv kubebuilder /usr/local/bin/

19-23: Add version validation

The version checks should validate that the installed tools meet minimum version requirements.

+# Function to compare versions
+version_check() {
+    local version=$1
+    local required=$2
+    if [ "$(printf '%s\n' "$required" "$version" | sort -V | head -n1)" = "$required" ]; then 
+        return 0
+    else
+        return 1
+    fi
+}
+
+# Check minimum versions
+MIN_KIND_VERSION="v0.20.0"
+MIN_KUBECTL_VERSION="v1.25.0"
+
 kind version
+KIND_VERSION=$(kind version | cut -d ' ' -f 2)
+if ! version_check "$KIND_VERSION" "$MIN_KIND_VERSION"; then
+    echo "Error: kind version $KIND_VERSION is less than required version $MIN_KIND_VERSION"
+    exit 1
+fi
+
 kubebuilder version
 docker --version
 go version
-kubectl version --client
+
+KUBECTL_VERSION=$(kubectl version --client -o json | jq -r '.clientVersion.gitVersion')
+if ! version_check "$KUBECTL_VERSION" "$MIN_KUBECTL_VERSION"; then
+    echo "Error: kubectl version $KUBECTL_VERSION is less than required version $MIN_KUBECTL_VERSION"
+    exit 1
+fi

1-23: Document the script's purpose and requirements

Add a header comment block to document the script's purpose, requirements, and usage.

Add this at the beginning of the script:

 #!/bin/bash
+# Purpose: Post-installation setup script for CozyStack Workload Controller development environment
+# Requirements:
+#   - Root privileges (sudo)
+#   - curl
+#   - Docker
+#   - Internet connectivity
+# Usage: ./post-install.sh
+
 set -euxo pipefail
packages/system/cozystack-workload-controller/config/rbac/workload_viewer_role.yaml (1)

1-8: LGTM! Consider adding documentation annotations.

The ClusterRole definition follows Kubernetes best practices with appropriate naming and standard labels. Consider adding annotations to document the role's purpose and usage.

metadata:
  labels:
    app.kubernetes.io/name: cozystack-workload-controller
    app.kubernetes.io/managed-by: kustomize
+ annotations:
+   cozystack.io/description: "Allows read-only access to workload resources"
+   cozystack.io/version: "v1"
  name: workload-viewer-role
packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml (1)

1-9: Enhance documentation and consider namespace scoping

The current documentation is minimal. Consider adding more detailed comments about:

  • The intended use of this role
  • Security implications of cluster-wide access
  • Whether this should be scoped to specific namespaces instead
-# permissions for end users to edit workloads.
+# This ClusterRole grants cluster-wide permissions for end users to manage workloads
+# in the cozystack.io API group. Consider using namespaced roles if cluster-wide
+# access is not required.
+#
+# Security Implications:
+# - Grants cluster-wide access to workload resources
+# - Should be carefully bound to trusted users/groups
packages/system/cozystack-workload-controller/Dockerfile (3)

6-12: Enhance security by verifying downloaded modules.

While the dependency caching strategy is optimal for build performance, consider adding module verification for enhanced security.

Apply this diff to enable module verification:

 COPY go.mod go.sum ./
-RUN go mod download
+RUN go mod verify && go mod download

14-17: Add .dockerignore file to optimize build context.

Consider adding a .dockerignore file to exclude unnecessary files (e.g., tests, documentation) from the build context. This will improve build performance and reduce image size.

Example .dockerignore content:

**/*_test.go
**/testdata
**/*.md
.git
.github
.gitignore

19-24: Enhance binary security and performance with additional build flags.

The build configuration is good, but could be enhanced with additional security and optimization flags.

Apply this diff to add security and optimization flags:

-RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go
+RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a \
+    -ldflags="-w -s" \
+    -trimpath \
+    -o manager cmd/main.go

These flags:

  • -ldflags="-w -s": Reduces binary size by removing debug information
  • -trimpath: Enhances reproducibility by removing file system paths
packages/system/cozystack-workload-controller/config/rbac/leader_election_role.yaml (1)

1-40: LGTM! Consider namespace scope restriction.

The Role configuration follows the standard controller-runtime pattern for leader election and grants appropriate permissions:

  • Full access to ConfigMaps and Leases for leader election
  • Limited Event access for logging

Consider adding a namespace selector in the metadata to explicitly scope this Role to the controller's namespace:

 metadata:
   labels:
     app.kubernetes.io/name: cozystack-workload-controller
     app.kubernetes.io/managed-by: kustomize
   name: leader-election-role
+  namespace: system
packages/system/cozystack-workload-controller/config/default/metrics_service.yaml (1)

1-17: Service configuration looks good!

The metrics service is well-configured with:

  • Appropriate labels for management and selection
  • Consistent port configuration (8443) with the manager patch
  • Correct protocol specification (TCP)
  • Proper pod selector matching controller-manager

Consider adding a comment block at the top of the file explaining the purpose of this service and its relationship with Prometheus monitoring, similar to the helpful comment in the NetworkPolicy file.

packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml (1)

1-26: Solid architecture for secure metrics exposure

The combination of these three configurations creates a well-structured and secure metrics setup:

  1. Manager patch exposes metrics on HTTPS port
  2. Service makes metrics accessible within the cluster
  3. NetworkPolicy restricts access to authorized namespaces

This follows the defense-in-depth principle and Kubernetes best practices for secure metrics exposure.

Consider adding the following to complete the metrics stack:

  1. ServiceMonitor/PodMonitor resource for Prometheus integration
  2. Grafana dashboards for visualizing the metrics
  3. Documentation for namespace labeling requirements
packages/system/cozystack-workload-controller/cmd/main.go (2)

1-15: Consider validating the Apache License header details.

The license header looks standard, but ensure the year ("2025") matches your intended release or copyright timeline.


95-97: Webhook server configuration.

Creating a webhook server with TLS options is aligned with recommended Kubernetes control plane security practices. Ensure that these settings match your production environment’s certificate strategy.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (3)

35-38: Consider adding concurrency safeguards
The WorkloadReconciler doesn’t explicitly utilize any concurrency control. If future enhancements involve parallel pod or workload operations, ensure you address concurrency concerns (e.g., multiple goroutines updating the same resource or status).


44-50: Add debug log when skipping unlabeled pods
When returning early because pod.Labels["workload.cozystack.io/kind"] is missing, consider adding a debug-level log. This can help identify pods that were intentionally skipped.

 if !hasKind {
+   logger.V(1).Info("Skipping Pod without 'workload.cozystack.io/kind' label", "pod", pod.Name)
    return ctrl.Result{}, nil
 }

129-139: Validate multi-owner scenarios
If multiple pods owned by different controllers mistakenly label the same Workload, the logic here deletes the Workload upon not finding the single “owner pod.” You may want to handle multi-owner or shared ownership cases more gracefully if applicable.

packages/system/cozystack-workload-controller/test/utils/utils.go (1)

39-41: Use structured logging instead of direct prints
warnError writes a warning to GinkgoWriter. Structured logs or returning an error might give more insights for debugging downstream.

packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (1)

281-283: Unnecessary conversion
json.Unmarshal([]byte(output), &token) can likely skip the []byte() cast if output is already a string. Check if the type of output is indeed string or []byte. Remove if redundant.

🧰 Tools
🪛 golangci-lint (1.62.2)

281-281: unnecessary conversion

(unconvert)

packages/system/cozystack-workload-controller/internal/controller/workload_controller_test.go (1)

69-82: Add deeper assertions
The test only checks for successful reconciliation without asserting changes to Workload resources or statuses. Consider verifying final states or intermediate statuses to ensure logic is correct.

packages/system/cozystack-workload-controller/internal/controller/suite_test.go (1)

55-73: Test Environment Initialization
The environment setup uses global variables like cfg, k8sClient, testEnv, and ctx. While reasonable for these tests, watch out if concurrency or parallel tests are added in the future. You might need to avoid global states or handle them with locks.

packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (1)

19-23: Command-Line Invocations & Logging
Running external processes like make generate or make manifests is a good strategy for building environment-specific artifacts. Consider capturing their combined output in logs or storing artifacts for debugging failures in CI.

packages/system/cozystack-workload-controller/.github/workflows/test.yml (2)

1-6: Workflow Trigger Scope
Running this workflow on both push and pull_request is good for continuous feedback. If you encounter concurrency or performance concerns, consider limiting triggers to specific branches or adding paths filters.


7-23: Go Environment, Commands, and Caching
The steps properly set up Go 1.22 and execute go mod tidy/make test. For performance gains on large repositories, consider enabling caching with the actions/cache action for your Go modules.

packages/system/cozystack-workload-controller/.github/workflows/test-e2e.yml (1)

15-19: Optimize workflow performance and reproducibility.

Consider these improvements:

  1. Pin the exact Go version for reproducibility
  2. Add Go modules cache to speed up builds

Apply these changes:

 - name: Setup Go
   uses: actions/setup-go@v5
   with:
-    go-version: '~1.22'
+    go-version: '1.22.0'
+    cache: true

Also applies to: 32-35

packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (1)

30-82: Add conversion strategy for future versions

As this is a v1alpha1 API, you should plan for future versions by defining a conversion strategy.

Consider adding:

  1. preserveUnknownFields: false at the schema root level
  2. Define a conversion webhook configuration for future version migrations
  3. Document the version compatibility strategy in the API documentation
packages/system/cozystack-workload-controller/config/manager/manager.yaml (2)

87-93: Review resource limits for production workload

The current resource limits might be too restrictive for production use:

  • CPU limit of 500m could throttle the controller
  • Memory limit of 128Mi might be insufficient for handling large clusters

Consider adjusting the resources:

  resources:
    limits:
-     cpu: 500m
-     memory: 128Mi
+     cpu: 1000m
+     memory: 512Mi
    requests:
-     cpu: 10m
-     memory: 64Mi
+     cpu: 100m
+     memory: 128Mi

31-50: Enable multi-architecture support

The commented node affinity configuration should be enabled to support multiple architectures.

Remove the TODO comment and uncomment the affinity section to support multiple architectures.

packages/system/cozystack-workload-controller/README.md (2)

48-48: Fix grammar in note about samples

There's a subject-verb agreement issue in the note about samples.

- Ensure that the samples has default values to test it out.
+ Ensure that the samples have default values to test them out.
🧰 Tools
🪛 LanguageTool

[grammar] ~48-~48: It looks like you are using the wrong form of the noun or the verb. Did you mean “sample has” or “samples have”?
Context: ...amples/ ``` >NOTE: Ensure that the samples has default values to test it out. ### To ...

(NOUN_PLURAL_HAS)


92-94: Complete contribution guidelines

The contribution section needs to be completed to encourage community participation.

Add:

  1. Development setup instructions
  2. Testing requirements
  3. Code style guidelines
  4. Pull request process
  5. Issue reporting guidelines
packages/system/cozystack-workload-controller/config/default/kustomization.yaml (1)

31-34: Consider enabling NetworkPolicy for enhanced security

The NetworkPolicy configuration is currently commented out. Given that the metrics endpoint is exposed, enabling NetworkPolicy would provide an additional security layer by controlling access to the metrics endpoint and webhook server.

packages/system/cozystack-workload-controller/Makefile (1)

66-71: Address the TODO comment for e2e test customization

The TODO comment indicates that e2e test vendor setup needs to be customized. Please provide documentation on how to use different vendors for e2e tests.

Would you like me to help create documentation for customizing e2e test vendors?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26388c7 and 9f38f3a.

⛔ Files ignored due to path filters (1)
  • packages/system/cozystack-workload-controller/go.sum is excluded by !**/*.sum
📒 Files selected for processing (49)
  • packages/system/cozystack-workload-controller/.devcontainer/devcontainer.json (1 hunks)
  • packages/system/cozystack-workload-controller/.devcontainer/post-install.sh (1 hunks)
  • packages/system/cozystack-workload-controller/.dockerignore (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/lint.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/test-e2e.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.github/workflows/test.yml (1 hunks)
  • packages/system/cozystack-workload-controller/.gitignore (1 hunks)
  • packages/system/cozystack-workload-controller/.golangci.yml (1 hunks)
  • packages/system/cozystack-workload-controller/Dockerfile (1 hunks)
  • packages/system/cozystack-workload-controller/Makefile (1 hunks)
  • packages/system/cozystack-workload-controller/PROJECT (1 hunks)
  • packages/system/cozystack-workload-controller/README.md (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/groupversion_info.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/kustomizeconfig.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/manager_metrics_patch.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/default/metrics_service.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/manager/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/manager/manager.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/network-policy/allow-metrics-traffic.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/network-policy/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/prometheus/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/leader_election_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/leader_election_role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/metrics_reader_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role_binding.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/service_account.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/workload_viewer_role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/samples/kustomization.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/samples/v1alpha1_workload.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/go.mod (1 hunks)
  • packages/system/cozystack-workload-controller/hack/boilerplate.go.txt (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/suite_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (1 hunks)
  • packages/system/cozystack-workload-controller/test/utils/utils.go (1 hunks)
✅ Files skipped from review due to trivial changes (13)
  • packages/system/cozystack-workload-controller/.dockerignore
  • packages/system/cozystack-workload-controller/hack/boilerplate.go.txt
  • packages/system/cozystack-workload-controller/config/network-policy/kustomization.yaml
  • packages/system/cozystack-workload-controller/config/samples/kustomization.yaml
  • packages/system/cozystack-workload-controller/config/prometheus/kustomization.yaml
  • packages/system/cozystack-workload-controller/config/samples/v1alpha1_workload.yaml
  • packages/system/cozystack-workload-controller/.gitignore
  • packages/system/cozystack-workload-controller/config/rbac/service_account.yaml
  • packages/system/cozystack-workload-controller/config/crd/kustomization.yaml
  • packages/system/cozystack-workload-controller/.github/workflows/lint.yml
  • packages/system/cozystack-workload-controller/api/v1alpha1/groupversion_info.go
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go
  • packages/system/cozystack-workload-controller/PROJECT
🧰 Additional context used
🪛 LanguageTool
packages/system/cozystack-workload-controller/README.md

[grammar] ~48-~48: It looks like you are using the wrong form of the noun or the verb. Did you mean “sample has” or “samples have”?
Context: ...amples/ ``` >NOTE: Ensure that the samples has default values to test it out. ### To ...

(NOUN_PLURAL_HAS)


[uncategorized] ~70-~70: A determiner appears to be missing. Consider inserting it.
Context: ... undeploy ``` ## Project Distribution Following are the steps to build the installer an...

(AI_EN_LECTOR_MISSING_DETERMINER)

🪛 Markdownlint (0.37.0)
packages/system/cozystack-workload-controller/README.md

107-107: Expected: fenced; Actual: indented
Code block style

(MD046, code-block-style)

🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/test/e2e/e2e_test.go

281-281: unnecessary conversion

(unconvert)


96-96: printf: non-constant format string in call to fmt.Fprintf

(govet)


98-98: printf: non-constant format string in call to fmt.Fprintf

(govet)


105-105: printf: non-constant format string in call to fmt.Fprintf

(govet)

packages/system/cozystack-workload-controller/test/utils/utils.go

95-95: unnecessary conversion

(unconvert)


156-156: unnecessary conversion

(unconvert)

🔇 Additional comments (46)
packages/system/cozystack-workload-controller/config/rbac/metrics_reader_role.yaml (1)

1-9: LGTM! The ClusterRole follows security best practices.

The implementation correctly:

  • Uses the stable RBAC API version
  • Follows the principle of least privilege by only allowing GET access to metrics
  • Provides appropriate scope for Prometheus metrics collection
packages/system/cozystack-workload-controller/config/rbac/kustomization.yaml (2)

12-20: Well-documented metrics protection configuration

The metrics endpoint protection is well-documented with clear references to the Kubebuilder documentation. The configuration follows best practices for securing metrics endpoints.


1-11: Verify RBAC completeness for controller operation

The core RBAC resources look comprehensive for a typical controller setup. However, let's verify that all necessary permissions are included.

Run this script to check for any missing RBAC configurations:

✅ Verification successful

Let me verify the referenced YAML files in the correct directory.


All required RBAC files are present and properly configured

The verification shows that all referenced YAML files exist in the correct directory with appropriate permissions:

  • Core RBAC files (service_account.yaml, role.yaml, role_binding.yaml)
  • Leader election files (leader_election_role.yaml, leader_election_role_binding.yaml)
  • Additional files for metrics and workload roles

The role definitions contain the necessary permissions:

  • Manager role has proper access to pods and workload resources
  • Leader election role includes required permissions for configmaps, leases, and events
  • Additional roles for metrics and workload management are present
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify RBAC completeness by checking referenced files and common patterns

# Check if all referenced YAML files exist
for file in service_account.yaml role.yaml role_binding.yaml leader_election_role.yaml leader_election_role_binding.yaml; do
  if ! [ -f "$file" ]; then
    echo "Warning: Referenced file $file not found"
  fi
done

# Check for common controller RBAC patterns in role definitions
rg -l 'kind:\s*Role|kind:\s*ClusterRole' | xargs rg -l 'rules:|apiGroups:|resources:|verbs:'

# Look for potential missing permissions in manager deployment
fd manager.yaml | xargs rg -A 5 'containers:'

Length of output: 12803


Script:

#!/bin/bash
# Check if all referenced YAML files exist in the correct directory
cd packages/system/cozystack-workload-controller/config/rbac/
ls -la *.yaml

# Check the content of role.yaml for comprehensive permissions
cat role.yaml

# Check leader election role
cat leader_election_role.yaml

Length of output: 2182

packages/system/cozystack-workload-controller/.golangci.yml (2)

1-43: LGTM! Comprehensive linter configuration.

The overall linter configuration is well-structured with a good selection of linters covering various aspects of code quality:

  • Code quality (govet, gosimple, staticcheck)
  • Style (gofmt, goimports)
  • Performance (prealloc)
  • Complexity (gocyclo)
  • Bug detection (errcheck, ineffassign)
  • Documentation (misspell)

The 5-minute timeout and parallel runners will help with performance on larger codebases.


11-18: Verify the excluded paths exist in the codebase.

The configuration excludes linters for specific paths. Let's verify these paths exist and contain the relevant code.

✅ Verification successful

✓ Excluded paths and their Go files are properly configured

The verification confirms that:

  • Both api/ and internal/ directories exist in the codebase
  • The api/ directory contains Go files including generated types and API definitions
  • The internal/ directory contains Go files including controllers and tests

These paths are valid targets for the linter exclusions in .golangci.yml, where:

  • api/* excludes the lll (line length) linter, which is common for generated files and API definitions
  • internal/* excludes dupl (code duplication) and lll linters, which is reasonable for implementation files
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of paths mentioned in exclude-rules

# Check if the paths exist
echo "Checking excluded paths..."
cd packages/system/cozystack-workload-controller
if [ -d "api" ]; then
    echo "✓ api/* path exists"
else
    echo "✗ api/* path not found"
fi

if [ -d "internal" ]; then
    echo "✓ internal/* path exists"
else
    echo "✗ internal/* path not found"
fi

Length of output: 260


Script:

#!/bin/bash
# Let's verify if these directories contain Go files that would be subject to linting

echo "Checking for Go files in api/ directory:"
fd -e go . packages/system/cozystack-workload-controller/api

echo -e "\nChecking for Go files in internal/ directory:"
fd -e go . packages/system/cozystack-workload-controller/internal

Length of output: 832

packages/system/cozystack-workload-controller/.devcontainer/devcontainer.json (2)

4-7: Consider security implications of Docker-in-Docker

While Docker-in-Docker is necessary for Kubernetes development, be aware of potential security implications:

  1. Privileged container execution
  2. Potential container escape vulnerabilities
  3. Shared Docker daemon resources

Consider implementing additional security measures such as:

  • Restricting container capabilities
  • Implementing resource limits
  • Using rootless Docker mode if possible

9-9: Review host network usage

Using --network=host bypasses container network isolation. While this might be necessary for local development:

  1. Document why host networking is required
  2. Consider using more restrictive networking options if possible
  3. Ensure this configuration is not propagated to production environments
packages/system/cozystack-workload-controller/config/rbac/workload_viewer_role.yaml (1)

18-23: Verify if status access is necessary for viewers.

The role grants read access to the workload status subresource. Consider if this level of access is necessary for regular viewers, as status information might contain internal details.

Run this script to understand how status information is used in the codebase:

✅ Verification successful

Let me gather more information about how the status is used in the codebase.


Let me gather one final piece of information about the status field contents.


Status access is appropriate for viewers

Based on the code analysis, the workload status contains basic operational information that is suitable for viewers:

  • Kind of workload (redis, postgres, etc.)
  • Type/role of the workload (e.g., redis, sentinel)
  • Allocated compute resources

This information is essential for users monitoring the workloads and doesn't expose any sensitive internal details. The status fields are well-defined and contain only high-level operational data that viewers would need to understand the workload's configuration.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how workload status is used in the codebase
# Look for references to workload status in Go files and CRD definitions

echo "Checking for status field usage in CRD definitions..."
fd -e yaml -e yml | xargs rg -l 'kind:\s*CustomResourceDefinition' | xargs rg -l 'cozystack.io/v1.*workload'

echo "Checking for status field usage in Go code..."
rg -A 5 'type WorkloadStatus struct' 

Length of output: 1043


Script:

#!/bin/bash
# Check for status usage in controllers and client code
echo "Checking for status field references in Go code..."
rg -A 3 'workload.*status' --type go

echo "Checking for status-related functions and methods..."
ast-grep --pattern 'func $$$Status$$$($$$) {
  $$$
}'

echo "Checking RBAC roles for comparison..."
fd -e yaml -e yml | xargs rg -l 'kind:\s*Role|kind:\s*ClusterRole' | xargs rg -C 5 'workloads/status'

Length of output: 4559


Script:

#!/bin/bash
# Check what information is stored in the status field
echo "Checking WorkloadStatus struct fields..."
rg -A 15 'type WorkloadStatus struct' --type go

echo "Checking status updates in controller..."
rg -B 3 -A 10 'Status.*workload' --type go

Length of output: 3484

packages/system/cozystack-workload-controller/config/rbac/workload_editor_role.yaml (1)

22-27: LGTM! Appropriate status access restrictions

The read-only access to workload status is correctly implemented, following the principle of least privilege by only allowing 'get' operations.

packages/system/cozystack-workload-controller/Dockerfile (2)

2-4: Consider pinning to a specific Go version for reproducible builds.

While using Go 1.22 is great for getting the latest features and improvements, consider pinning to a specific patch version (e.g., golang:1.22.0) to ensure reproducible builds across different environments.

Let's verify if Go 1.22 is stable and appropriate for production use:

✅ Verification successful

Go 1.22 is a stable version, but consider pinning to a specific patch version

While Go 1.22 is a stable release suitable for production use, it's recommended to pin to a specific patch version (e.g., golang:1.22.10) to ensure reproducible builds across different environments. This helps prevent unexpected behavior from patch updates and maintains consistency in your build process.

Example:

FROM golang:1.22.10 AS builder
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check the latest stable Go versions and their release dates
curl -s https://go.dev/dl/?mode=json | jq '.[0:3] | .[] | {version: .version, stable: .stable, release_date: .files[0].date}'

Length of output: 270


28-32: Enhance security with additional hardening measures.

The use of distroless and non-root user is excellent for security. Consider these additional enhancements:

  1. Pin the distroless image to a specific SHA for immutability:
-FROM gcr.io/distroless/static:nonroot
+FROM gcr.io/distroless/static:nonroot@sha256:abc123...  # Replace with actual SHA
  1. Add security options to prevent privilege escalation:
 USER 65532:65532
+
+# Add security options
+LABEL io.container.security.capabilities='["AUDIT_WRITE", "NET_BIND_SERVICE"]'
+LABEL io.container.drop-capabilities='["ALL"]'

Let's verify the latest distroless image SHA:

packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role.yaml (1)

1-17: LGTM! Well-structured RBAC configuration following security best practices.

The ClusterRole follows the principle of least privilege by:

  • Granting only the required 'create' permission
  • Limiting scope to specific resources (tokenreviews and subjectaccessreviews)
  • Using precise API group specifications
packages/system/cozystack-workload-controller/config/rbac/metrics_auth_role_binding.yaml (1)

1-12: LGTM! Verify referenced ServiceAccount exists.

The ClusterRoleBinding configuration is correct and properly references the metrics-auth-role.

Let's verify the existence of the referenced ServiceAccount:

✅ Verification successful

ServiceAccount verification successful

The controller-manager ServiceAccount exists in the system namespace and is properly defined in config/rbac/service_account.yaml. The ClusterRoleBinding configuration is correctly referencing this ServiceAccount.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the controller-manager ServiceAccount is defined
fd -t f "service_account.yaml" | xargs grep -l "controller-manager"

Length of output: 144


Script:

#!/bin/bash
# Let's verify the content of the service account file
cat packages/system/cozystack-workload-controller/config/rbac/service_account.yaml

Length of output: 289

packages/system/cozystack-workload-controller/config/rbac/role_binding.yaml (2)

4-7: LGTM! Well-structured labels following Kubernetes conventions.

The metadata labels follow Kubernetes best practices by including:

  • app.kubernetes.io/name for application identification
  • app.kubernetes.io/managed-by for tooling identification

8-15: Verify the referenced manager-role exists with appropriate permissions.

The binding references a ClusterRole named 'manager-role' which should contain the core permissions for the workload controller.

Let's verify the referenced ClusterRole:

✅ Verification successful

Let me gather more information about the specific ClusterRole permissions for the workload controller.


The referenced manager-role exists with appropriate RBAC permissions for the workload controller

The ClusterRole 'manager-role' is properly defined with the necessary permissions for the workload controller to function:

  • Core pod operations: get, list, watch on pods
  • Full CRUD operations on workloads.cozystack.io resources
  • Status subresource access for workloads

The permissions align with what would be expected for a workload controller managing custom workload resources and monitoring pods.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if manager-role is defined and examine its permissions
fd -t f "role.yaml" | xargs grep -l "manager-role"

# Examine the permissions granted to the role
rg -A 10 "name: manager-role" 

Length of output: 3987


Script:

#!/bin/bash
# Get the complete content of the workload controller's role.yaml to examine all permissions
cat packages/system/cozystack-workload-controller/config/rbac/role.yaml

Length of output: 490

packages/system/cozystack-workload-controller/config/rbac/leader_election_role_binding.yaml (1)

1-15: LGTM! Verify ServiceAccount existence.

The RoleBinding configuration is correct and follows Kubernetes RBAC best practices. The binding properly associates the leader-election-role with the controller-manager ServiceAccount.

Let's verify the existence of the referenced ServiceAccount:

✅ Verification successful

The previous search might have been too specific with the regex pattern. Let's broaden our search to find any ServiceAccount definitions and specific references to the controller-manager ServiceAccount in the YAML files.


Let's check specifically in the config directory where the RoleBinding is located to find the corresponding ServiceAccount definition and any related references.


ServiceAccount exists and is properly configured

The ServiceAccount controller-manager exists in the config/rbac/service_account.yaml file and is properly referenced in the RoleBinding. The search results show that the ServiceAccount is used consistently across the codebase, particularly in:

  • config/rbac/service_account.yaml: Defines the ServiceAccount
  • config/manager/manager.yaml: Uses the ServiceAccount in the controller deployment
  • config/rbac/leader_election_role_binding.yaml: References the ServiceAccount in the RoleBinding (the file under review)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of the controller-manager ServiceAccount
rg -l "kind: ServiceAccount.*name: controller-manager.*namespace: system" -t yaml

Length of output: 83


Script:

#!/bin/bash
# Let's try a broader search for ServiceAccount definitions
fd -e yaml -e yml | xargs rg "kind: ServiceAccount" -A 3 -B 1

# Also search for any references to controller-manager ServiceAccount
fd -e yaml -e yml | xargs rg "controller-manager" -A 2 -B 2

Length of output: 81717


Script:

#!/bin/bash
# Let's search specifically for the ServiceAccount definition in the config directory
fd "serviceaccount.*\.ya?ml" config/ | xargs cat

# Also search for any references to controller-manager ServiceAccount in the config directory
fd -e yaml -e yml config/ | xargs rg "controller-manager" -A 2 -B 2

Length of output: 43409

packages/system/cozystack-workload-controller/config/rbac/role.yaml (1)

1-34: LGTM! Verify CRD existence.

The ClusterRole follows the principle of least privilege and grants appropriate permissions:

  • Read-only access to pods for monitoring
  • Full access to workload resources in cozystack.io API group
  • Status subresource access for workload status updates

Let's verify the existence of the Workload CRD:

✅ Verification successful

✓ ClusterRole permissions align with CRD definition

The ClusterRole permissions are correctly defined as the Workload CRD exists in the cozystack.io API group with:

  • Proper CRD definition at config/crd/bases/cozystack.io_workloads.yaml
  • Matching API group (cozystack.io)
  • Matching resource name (workloads)
  • Status subresource support via schema definition

The role grants exactly the permissions needed for the controller to manage Workload resources and their status.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of the Workload CRD in cozystack.io API group
rg -l "kind: CustomResourceDefinition.*name: workloads.cozystack.io" -t yaml

Length of output: 78


Script:

#!/bin/bash
# Let's try different approaches to find the CRD definition

# Search for CRD files in config/crd directory (common location)
fd -t f . "config/crd"

# Search for any yaml files containing workload CRD definition with different patterns
rg -t yaml "apiVersion: apiextensions.k8s.io.*kind: CustomResourceDefinition" -A 5

# Search specifically for workload-related yaml files
fd -t f -e yaml . | grep -i "workload"

Length of output: 2385


Script:

#!/bin/bash
# Let's examine the CRD definition file we found
cat packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml

Length of output: 3062

packages/system/cozystack-workload-controller/cmd/main.go (7)

28-41: Imports and references appear appropriate.

Importing the Kubernetes client-go and controller-runtime libraries is correctly handled, and referencing the internal and external CozyStack APIs follows best practices.


48-53: Good practice adding CRD schemes in init().

Registering the default Kubernetes client scheme and your custom CozyStack API scheme allows the manager to handle Kubernetes objects and custom resource definitions.


55-77: Flag handling is clear and comprehensive.

Defining flags for metrics address, leader election, probe address, secure metrics, and HTTP/2 ensures flexibility. This is a common and well-structured approach in controller code.


80-93: Smart handling of HTTP/2 vulnerabilities.

Conditionally disabling HTTP/2 is a prudent measure given its known vulnerabilities. The approach of customizing tls.Config’s NextProtos is appropriate.


103-119: Metrics server setup is thorough.

The secure metrics approach using FilterProvider for authentication and authorization is appropriate. For production, finalize the certificate configuration to avoid automatically generated self-signed certs.


145-151: Controller setup is implemented properly.

The WorkloadReconciler is correctly attached to the manager. Logging errors and exiting on failure ensures quick detection of startup problems.


154-168: Health checks and manager startup appear correct.

The readiness and liveness checks use healthz.Ping, providing basic coverage. This is typically sufficient, though additional checks can ensure deeper system verification. The signal handler nicely handles manager termination.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (2)

1-15: License Header Verified
Everything in the license header appears valid and up-to-date.


76-84: Consider failing reconciliation on resource parse errors
Lines 77-84 log parse failures for resource quantities but continue instead of failing the reconciliation. If partial resource data is critical, you might want to return an error and retry. Decide whether partial data is acceptable.

packages/system/cozystack-workload-controller/test/utils/utils.go (2)

48-50: Confirm directory change side-effects
Line 48 changes the process’s working directory globally. This can lead to subtle side-effects if multiple tests run in parallel. Consider localizing directory changes or capturing the directory state beforehand to avoid concurrency pitfalls.


148-155: Add fallback or partial checks for CRDs
IsCertManagerCRDsInstalled returns false immediately if any CRD isn’t found. If partial CRDs are sometimes acceptable or loaded asynchronously, consider clarifying or refactoring the logic to differentiate partial success vs. total failure.

packages/system/cozystack-workload-controller/test/e2e/e2e_test.go (1)

186-189: Avoid storing secrets in variables
Line 188 prints out the token in plain text if it fails certain checks. Consider redacting or limiting its exposure in logs, especially if the logs are publicly visible.
[security]

packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (2)

40-42: Consider making Resources field optional
Lines 40–42 specify Resources as +required. If partial or unknown resource sets might be valid, consider making the field optional or adding validation logic.


69-71: Schema registration validated
Registration of Workload and WorkloadList looks correct and survivable across module boundaries.

packages/system/cozystack-workload-controller/internal/controller/workload_controller_test.go (1)

45-58: Ensure resource creation covers concurrency
Currently if multiple tests create the same named resource, collisions could arise. Confirm that test runs are isolated or that resource names are unique per test run.

packages/system/cozystack-workload-controller/internal/controller/suite_test.go (3)

1-15: License and File Header Check
The license header appears standardized and complete. Good job including the year and Apache License details. Make sure this header remains consistent across all new files.


49-53: Test Suite Initialization
This Ginkgo-based setup is a good approach for organizing tests. Everything looks standard, and the test suite name "Controller Suite" is concise and descriptive.


91-96: Ensure Cleanup on Errors
Although you are calling testEnv.Stop() in the AfterSuite, consider edge cases if the setup partially fails. Ginkgo does well with this, but verifying partial cleanups can prevent resource leaks in ephemeral environments.

packages/system/cozystack-workload-controller/test/e2e/e2e_suite_test.go (4)

1-15: License and File Header Check
The license block is present and properly references the Apache License. This is consistent with other parts of the repository.


59-83: Building & Loading the Image into Kind
This code effectively validates that the operator image is built and loaded into the Kind cluster. Nice tactic for end-to-end coverage.


87-107: Conditional Prometheus/CertManager Installation
Handling the possibility of pre-installed CRDs is a smart approach. The checks look robust. One small note: if partial installations occur (e.g., leftover CRDs without fully running controllers), you may need extended checks for actual controller readiness.


110-120: Teardown Logic
Good job handling both skip and preinstallation scenarios to avoid unnecessary uninstalls. This logic helps maintain a clean testing environment.

packages/system/cozystack-workload-controller/config/manager/kustomization.yaml (1)

1-2: Resources Configuration
Listing manager.yaml under resources is consistent with typical Kustomize conventions. Confirm that this file is referenced in any relevant overlay or base to ensure correct layering in multi-environment deployments.

packages/system/cozystack-workload-controller/config/crd/kustomizeconfig.yaml (1)

1-19: LGTM! Standard Kustomize configuration for CRD webhooks.

The configuration correctly defines name references and namespace handling for CRD webhook configurations, following Kustomize best practices.

packages/system/cozystack-workload-controller/config/prometheus/monitor.yaml (1)

1-16: LGTM! ServiceMonitor configuration follows best practices.

The configuration correctly sets up:

  • Appropriate labels for control plane components
  • Bearer token authentication
  • Metrics endpoint configuration

Also applies to: 28-30

packages/system/cozystack-workload-controller/go.mod (1)

8-10: LGTM! Kubernetes dependencies are well-aligned

All Kubernetes-related dependencies (client-go, apimachinery, api) are consistently using version v0.31.0, which is good for compatibility.

packages/system/cozystack-workload-controller/config/default/kustomization.yaml (1)

21-27: LGTM! Well-documented optional features

The configuration clearly documents how to enable optional features like webhooks, cert-manager, and Prometheus monitoring with helpful comments and instructions.

packages/system/cozystack-workload-controller/Makefile (2)

118-127: LGTM! Excellent cross-platform build support

The Makefile includes comprehensive support for cross-platform builds using Docker buildx, covering major architectures (arm64, amd64, s390x, ppc64le). The implementation properly handles:

  • BuildKit configuration
  • Platform-specific Dockerfile generation
  • Cleanup of temporary resources

173-176: LGTM! Well-maintained tool versions

All tool versions are explicitly defined and use recent stable versions:

  • kustomize: v5.5.0
  • controller-tools: v0.16.4
  • envtest: release-0.19
  • golangci-lint: v1.61.0

Comment on lines +44 to +47
linters-settings:
revive:
rules:
- name: comment-spacings

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.

🛠️ Refactor suggestion

Complete the revive rule configuration.

The comment-spacings rule configuration appears incomplete. The rule typically requires additional parameters to specify the exact spacing requirements.

Consider completing the rule configuration:

 linters-settings:
   revive:
     rules:
-      - name: comment-spacings
+      - name: comment-spacings
+        arguments:
+          - always
+          - "/*"
+          - "/**"

This configuration ensures consistent comment spacing throughout the codebase.

📝 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
linters-settings:
revive:
rules:
- name: comment-spacings
linters-settings:
revive:
rules:
- name: comment-spacings
arguments:
- always
- "/*"
- "/**"

@@ -0,0 +1,25 @@
{
"name": "Kubebuilder DevContainer",
"image": "golang:1.22",

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

Use the latest stable Go version

The specified Go version 1.22 is currently in beta and not yet officially released. Consider using the latest stable version (1.21) to avoid potential compatibility issues.

-  "image": "golang:1.22",
+  "image": "golang:1.21",
📝 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
"image": "golang:1.22",
"image": "golang:1.21",

Comment on lines +13 to +15
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},

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.

🛠️ Refactor suggestion

Update deprecated VSCode terminal setting

The terminal.integrated.shell.linux setting is deprecated. Use the newer terminal.integrated.defaultProfile.linux setting instead.

-        "terminal.integrated.shell.linux": "/bin/bash"
+        "terminal.integrated.defaultProfile.linux": "bash"
📝 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
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},

Comment on lines +1 to +2
#!/bin/bash
set -x

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.

🛠️ Refactor suggestion

Add error handling and strict mode

While set -x is good for debugging, consider adding these bash safety flags:

  • set -e: Exit on error
  • set -u: Exit on undefined variables
  • set -o pipefail: Exit on pipe failures
 #!/bin/bash
-set -x
+set -euxo pipefail
📝 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
#!/bin/bash
set -x
#!/bin/bash
set -euxo pipefail

Comment on lines +4 to +6
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

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

Verify downloaded binaries

Downloads should include checksum verification to ensure integrity and prevent supply chain attacks.

+# Download and verify kind
 curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
+curl -Lo ./kind.sha256 https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64.sha256
+echo "$(<kind.sha256) kind" | sha256sum --check
 chmod +x ./kind
 mv ./kind /usr/local/bin/kind
📝 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
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind
# Download and verify kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
curl -Lo ./kind.sha256 https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64.sha256
echo "$(<kind.sha256) kind" | sha256sum --check
chmod +x ./kind
mv ./kind /usr/local/bin/kind

Comment on lines +52 to +54
spec:
description: WorkloadSpec defines the desired state of Workload
type: object

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

Define validation rules for the spec section

The spec section is currently empty, which means any arbitrary data can be stored. This could lead to inconsistencies and make it difficult to validate workload configurations.

Consider adding validation rules for workload specifications. For example:

spec:
  description: WorkloadSpec defines the desired state of Workload
  type: object
  properties:
    replicas:
      type: integer
      minimum: 0
    template:
      type: object
      required:
        - kind
    resources:
      type: object
  required:
    - template

Comment on lines +62 to +71
resources:
additionalProperties:
anyOf:
- type: integer
- type: string
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
description: Resources specifies the compute resources allocated to
this workload
type: object

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.

🛠️ Refactor suggestion

Add validation rules for resource quantities

The resources field allows any string or integer value without proper validation of Kubernetes resource quantities.

Add specific pattern validation for resource quantities. Example:

resources:
  type: object
  properties:
    cpu:
      type: string
      pattern: ^([0-9]+m?|[0-9]+\.[0-9]+)$
    memory:
      type: string
      pattern: ^[0-9]+(Gi|Mi|Ki|G|M|K)?$
  required:
    - cpu
    - memory

Comment on lines +51 to +60
securityContext:
runAsNonRoot: true
# TODO(user): For common cases that do not require escalating privileges
# it is recommended to ensure that all your Pods/Containers are restrictive.
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
# seccompProfile:
# type: RuntimeDefault
containers:

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.

🛠️ Refactor suggestion

Enable SecurityContext seccompProfile

The commented seccompProfile should be enabled for enhanced security.

Remove the TODO comment and uncomment the seccompProfile section:

  securityContext:
    runAsNonRoot: true
-   # seccompProfile:
-   #   type: RuntimeDefault
+   seccompProfile:
+     type: RuntimeDefault
📝 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
securityContext:
runAsNonRoot: true
# TODO(user): For common cases that do not require escalating privileges
# it is recommended to ensure that all your Pods/Containers are restrictive.
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
# seccompProfile:
# type: RuntimeDefault
containers:
securityContext:
runAsNonRoot: true
# TODO(user): For common cases that do not require escalating privileges
# it is recommended to ensure that all your Pods/Containers are restrictive.
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
seccompProfile:
type: RuntimeDefault
containers:

Comment on lines +1 to +6
# cozystack-workload-controller
// TODO(user): Add simple overview of use/purpose

## Description
// TODO(user): An in-depth paragraph about your project and overview of use

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.

🛠️ Refactor suggestion

Add project overview and description

The TODO placeholders for project overview and description should be filled with actual content to help users understand the purpose and functionality of the workload controller.

Consider adding:

  1. Clear description of what a "workload" represents in your system
  2. Use cases and examples
  3. Architecture overview
  4. Integration points with other components

@@ -0,0 +1,98 @@
module github.com/aenix-io/cozystack

go 1.22.0

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.

💡 Codebase verification

Go version inconsistency detected across modules

The repository contains multiple Go modules with different Go versions:

  • Main module uses Go 1.23.0
  • Workload controller module uses Go 1.22.0

This inconsistency could lead to:

  • Confusion in development environments
  • Potential compatibility issues
  • Inconsistent behavior across modules

Recommendation:

  • Align Go versions across all modules, preferably to Go 1.23.0 which is already used in the main module
  • Update the workload controller's go.mod to match the main module's Go version
🔗 Analysis chain

Consider the implications of using Go 1.22.0

While using the latest Go version (1.22.0) provides access to new features and improvements, it's worth noting that it's a very recent release (February 2024). This might impact:

  • CI/CD systems that need to support this version
  • Development environments that need to be updated
  • Potential early-version issues
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if CI/CD workflows specify Go 1.22
rg -l "go-version.*1\.22" .github/

Length of output: 36


Script:

#!/bin/bash
# Check for Go version in GitHub workflows with a broader pattern
fd workflow .github -x cat {} \; | grep -i "go-version"

# Check for any other Go version specifications in the repository
fd "go.mod|go.work" -x cat {}

Length of output: 10036

@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: 1

🧹 Nitpick comments (3)
packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (2)

25-27: Consider adding fields or removing the empty struct.

Currently, WorkloadSpec is completely empty. If there are no immediate plans to expose configuration through the spec, you can either remove the struct for now or add placeholder fields and validation rules.


31-47: Ensure status fields cover all operational aspects.

WorkloadStatus captures essential fields (Kind, Type, Resources, Operational). Consider if additional fields (e.g., reason or phase) might better describe the workload’s state, especially when diagnosing partial failures or slow startups.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1)

95-101: Reconsider using the Pod’s name for the Workload resource.

Tying the Workload resource name directly to the Pod name can cause fragmentation during rolling updates or restarts, as Pod names typically change. Consider applying a consistent naming pattern or using labels instead.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f38f3a and fa6e0db.

📒 Files selected for processing (3)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1 hunks)
🔇 Additional comments (3)
packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (2)

56-59: Define validation rules for spec.
The spec section is declared as an empty object, which allows any arbitrary data. Consider specifying validation rules or minimal fields (e.g., replicas, resources, or template) to avoid misconfiguration.


92-92: Enable status or scale subresources for better controller management.
Using subresources: {} disables subresource updates for status or scale. Enabling the status subresource helps standardize status updates, and the scale subresource facilitates HPA integration.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1)

139-149: Good approach to cleaning up orphaned workloads.

Deleting the Workload when its owner Pod is missing prevents orphaned resources. This is a clean strategy to maintain consistency and free up resources in your cluster.

Comment on lines +66 to +76
resources := map[string]resource.Quantity{}
for _, container := range pod.Spec.Containers {
for resourceName, quantity := range container.Resources.Limits {
if existing, exists := resources[resourceName.String()]; exists {
existing.Add(quantity)
resources[resourceName.String()] = existing
} else {
resources[resourceName.String()] = quantity
}
}
}

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.

🛠️ Refactor suggestion

Account for resource requests or ephemeral storage if required.

The code sums container limits into Resources, but doesn't account for requests or ephemeral volumes. If you intend to track actual usage or scheduling constraints, include requests and additional resource types (like ephemeral storage).

@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: 1

🧹 Nitpick comments (2)
packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (2)

1-2: Update the copyright year

The copyright year is set to 2025, which is in the future. Please update it to the current year (2024).

-Copyright 2025.
+Copyright 2024.

35-38: Add validation for required resource types

The Resources map allows any string key, but the print columns (lines 47-48) expect specific keys cpu and memory. Consider adding validation to ensure these required resources are always present.

Consider adding a validation webhook or using OpenAPI v3 schema validation:

// +kubebuilder:validation:Required=cpu,memory
Resources map[string]resource.Quantity `json:"resources"`
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fa6e0db and ce6e96f.

📒 Files selected for processing (2)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloads.yaml
🔇 Additional comments (3)
packages/system/cozystack-workload-controller/api/v1alpha1/workload_types.go (3)

61-66: LGTM!

The WorkloadList implementation correctly follows Kubernetes list type conventions.


68-70: LGTM!

The init function correctly registers the types with the SchemeBuilder.


26-33: Verify label consistency with workload kinds

The PR description mentions specific workload labels (workload.cozystack.io/kind=redis, workload.cozystack.io/type=sentinel). Let's verify that these labels are consistently used across the codebase.

✅ Verification successful

Label implementation aligns with design

The workload controller correctly implements the label structure described in the PR:

  • Required workload.cozystack.io/kind label matches the required Kind field
  • Optional workload.cozystack.io/type label matches the optional Type field, defaulting to the kind value
  • Implementation allows for the example use cases (redis/sentinel) while remaining generic for future workload types
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for workload label usage to ensure consistency
rg -g '!vendor' -g '!*.yaml' -A 2 'workload\.cozystack\.io/(kind|type)'

# Search for predefined workload kinds/types
ast-grep --pattern 'const (
  $$$
  Workload$_Kind$_ = $_
  $$$
)'

Length of output: 1259


Script:

#!/bin/bash
# Search for validation logic
ast-grep --pattern 'func (w *Workload) Validate() error {
  $$$
}'

# Search for additional label-related code
rg -g '!vendor' -g '!*.yaml' 'workload\.cozystack\.io' -A 3

Length of output: 2151

Comment on lines +44 to +57
// +kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Kind",type="string",JSONPath=".status.kind"
// +kubebuilder:printcolumn:name="Type",type="string",JSONPath=".status.type"
// +kubebuilder:printcolumn:name="CPU",type="string",JSONPath=".status.resources.cpu"
// +kubebuilder:printcolumn:name="Memory",type="string",JSONPath=".status.resources.memory"
// +kubebuilder:printcolumn:name="Operational",type="boolean",JSONPath=`.status.operational`

// Workload is the Schema for the workloads API
type Workload struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Status WorkloadStatus `json:"status,omitempty"`
}

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.

🛠️ Refactor suggestion

Consider adding standard CRD elements

The Workload CRD is missing several standard elements:

  1. No Spec field, which is unusual for Kubernetes CRDs
  2. Missing status subresource marker
  3. Missing version/group markers

Consider adding these elements:

 // +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:resource:scope=Namespaced,shortName=wl
+// +groupName=cozystack.io
 
 type Workload struct {
     metav1.TypeMeta   `json:",inline"`
     metav1.ObjectMeta `json:"metadata,omitempty"`
 
+    // +optional
+    Spec WorkloadSpec `json:"spec,omitempty"`
     Status WorkloadStatus `json:"status,omitempty"`
 }

Committable suggestion skipped: line range outside the PR's diff.

@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: 1

🧹 Nitpick comments (5)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (3)

19-23: Add error-handling helpers for improved resilience.

The WorkloadMonitorReconciler struct is straightforward, but consider adding helper methods or dedicated error-handling logic to keep the Reconcile() method concise and robust.


61-74: Evaluate concurrency for large workload sets.

Iterating over many workloads in a single loop might become a performance bottleneck under high loads. Consider chunking or concurrency if you anticipate large workload sets.


83-123: Periodic requeue might lead to high cluster churn.

Requeuing every 30 seconds may be too frequent if you have many WorkloadMonitor objects. Adjust RequeueAfter based on typical workload lifecycles or make it configurable.

packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go (2)

8-27: Validate user inputs.

The WorkloadMonitorSpec uses numeric fields like MinReplicas and Replicas. Although you have Minimum=0, consider additional validations (e.g., max value if relevant) or explicit validations in the reconciler logic for edge cases.


74-80: Prefer consistent naming for label selectors.

Selector is defined as map[string]string, but your spec calls it Selector map[string]string too. This is consistent, but consider referencing the type alias in your WorkloadMonitorSpec to avoid repetition.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce6e96f and 9c7fd1d.

📒 Files selected for processing (7)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloadmonitors.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/system/cozystack-workload-controller/cmd/main.go
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml
🔇 Additional comments (14)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (3)

25-29: RBAC rules seem appropriate.

The RBAC annotations cover the main verbs for both WorkloadMonitor and Workload resources to ensure the reconciler’s functionality. No issues noted.


30-42: Gracefully handle missing CR scenario.

The logic correctly exits when the WorkloadMonitor is not found (line 38). Good defensive programming approach to prevent extraneous errors or logs when the resource is deleted.


125-161: Watch logic is solid.

Watching Workload updates and triggering reconciliation via EnqueueRequestsFromMapFunc is well organized and aligns with best practices.

packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go (2)

29-42: Status definitions are clear.

The WorkloadMonitorStatus fields are straightforward. No obvious issues with the chosen field types or naming.


44-60: Adherence to Kubernetes conventions.

The annotations (+kubebuilder:object:root=true, subresource status, and printer columns) conform to K8s CRD conventions and ensure the CRD is well-exposed.

packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloadmonitors.yaml (3)

1-8: CRD name alignment check.

workloadmonitors.cozystack.io matches the group descriptor in your code. Good for CRD versioning alignment.


17-32: Helpful printer columns.

Including columns for version, minReplicas, available, observed, and operational helps operators quickly identify the resource state.


56-81: Schema definitions are well-structured.

The schema enforces proper types (minimum: 0 for replicas, etc.). Very comprehensive coverage of spec and status.

packages/system/cozystack-workload-controller/internal/controller/workload_controller.go (4)

44-51: Check readiness for multi-container pods.

isPodReady checks only top-level readiness conditions; this is correct for standard usage. Ensure you’ve validated readiness gates if your cluster uses them.


66-76: **** Account for resource requests or ephemeral storage.


78-93: Validate annotation resource format carefully.

You correctly catch JSON parse errors but consider validating the resource names. A malformed resource key can silently degrade the system’s reporting or reconciliation accuracy.


126-154: Deletion logic for orphan workloads.

If the owner Pod is not found, you delete the Workload. This approach is consistent with standard K8s GC patterns.

packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go (2)

28-48: Confirm coverage of all map fields.

The code copies each key-value pair for Selector. Confirm that no new fields were added to Selector that must also be copied.


214-223: Great approach for copying resource quantities.

DeepCopy ensures each quantity is individually copied, preventing accidental references.

Comment on lines +53 to +93
func (r *WorkloadReconciler) reconcilePod(ctx context.Context, pod *corev1.Pod) (ctrl.Result, error) {
logger := log.FromContext(ctx)

kind, hasKind := pod.Labels["workload.cozystack.io/kind"]
if !hasKind {
return ctrl.Result{}, nil
}

workloadType, hasType := pod.Labels["workload.cozystack.io/type"]
if !hasType {
workloadType = kind
}

resources := map[string]resource.Quantity{}
for _, container := range pod.Spec.Containers {
for resourceName, quantity := range container.Resources.Limits {
if existing, exists := resources[resourceName.String()]; exists {
existing.Add(quantity)
resources[resourceName.String()] = existing
} else {
resources[resourceName.String()] = quantity
}
}
}

if resourcesStr, ok := pod.Annotations["workload.cozystack.io/resources"]; ok {
var annotationResources map[string]string
if err := json.Unmarshal([]byte(resourcesStr), &annotationResources); err != nil {
logger.Error(err, "Failed to parse resources annotation")
return ctrl.Result{}, err
}

for name, value := range annotationResources {
quantity, err := resource.ParseQuantity(value)
if err != nil {
logger.Error(err, "Failed to parse resource quantity", "resource", name, "value", value)
continue
}
resources[name] = quantity
}
}

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.

🛠️ Refactor suggestion

Consider using container requests to reflect actual resource usage.

Aggregating only Limits may overlook Requests. If you want to track real usage or scheduling constraints, also parse and store container resource requests.

@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: 1

🧹 Nitpick comments (5)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (5)

37-43: Enhance error handling

Consider adding more context to error logging by including the WorkloadMonitor name and namespace.

-		logger.Error(err, "Unable to fetch WorkloadMonitor")
+		logger.Error(err, "Unable to fetch WorkloadMonitor",
+			"name", req.Name,
+			"namespace", req.Namespace)

83-92: Clarify operational status logic

The operational status logic could be more explicit. Consider extracting it into a separate method for better readability and testability.

+func (r *WorkloadMonitorReconciler) isOperational(availableReplicas int32, minReplicas *int32) bool {
+	if minReplicas == nil {
+		return true
+	}
+	return availableReplicas >= *minReplicas
+}

-	// Initially set operational = true
-	monitor.Status.Operational = pointer.Bool(true)
-
-	// If there are less available replicas than minReplicas, set false
-	if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas {
-		monitor.Status.Operational = pointer.Bool(false)
-		logger.Info("Available replicas below minimum",
-			"available", availableReplicas,
-			"minimum", *monitor.Spec.MinReplicas)
-	}
+	monitor.Status.Operational = ptr.To(r.isOperational(availableReplicas, monitor.Spec.MinReplicas))
+	if !*monitor.Status.Operational {
+		logger.Info("Available replicas below minimum",
+			"available", availableReplicas,
+			"minimum", *monitor.Spec.MinReplicas)
+	}

106-108: Make requeue interval configurable

The 30-second requeue interval is hardcoded. Consider making it configurable through the WorkloadMonitor spec or controller configuration.

+const defaultRequeueInterval = 30 * time.Second

+	interval := defaultRequeueInterval
+	if monitor.Spec.SyncInterval != nil {
+		interval = monitor.Spec.SyncInterval.Duration
+	}
-	return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
+	return ctrl.Result{RequeueAfter: interval}, nil

115-144: Optimize the mapping function implementation

The mapping function could be improved in several ways:

  1. Better error handling
  2. Extracted selector matching logic
  3. Early returns for better readability
+func matchesSelector(workload *cozyv1alpha1.Workload, selector map[string]string) bool {
+	for k, v := range selector {
+		if workload.Labels[k] != v {
+			return false
+		}
+	}
+	return true
+}

 handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
 	workload := obj.(*cozyv1alpha1.Workload)
+	logger := log.FromContext(ctx)

 	// List all WorkloadMonitors
 	monitorList := &cozyv1alpha1.WorkloadMonitorList{}
 	if err := r.List(ctx, monitorList, client.InNamespace(workload.Namespace)); err != nil {
+		logger.Error(err, "Failed to list WorkloadMonitors",
+			"workload", workload.Name,
+			"namespace", workload.Namespace)
 		return nil
 	}

+	if len(monitorList.Items) == 0 {
+		return nil
+	}

 	var requests []reconcile.Request
 	// Check each monitor's selector
 	for _, monitor := range monitorList.Items {
-		matches := true
-		for k, v := range monitor.Spec.Selector {
-			if workload.Labels[k] != v {
-				matches = false
-				break
-			}
-		}
-		if matches {
+		if matchesSelector(workload, monitor.Spec.Selector) {
 			requests = append(requests, reconcile.Request{
 				NamespacedName: types.NamespacedName{
 					Name:      monitor.Name,

1-146: Overall implementation is well-structured

The WorkloadMonitor controller implementation follows Kubernetes controller patterns and best practices. While there are several suggested improvements, the core functionality is solid and maintainable.

Consider adding metrics for:

  • Reconciliation duration
  • Number of workloads being monitored
  • Number of operational vs non-operational workloads
    This will help with monitoring the controller's performance and the health of the workloads it monitors.
🧰 Tools
🪛 golangci-lint (1.62.2)

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cce7c75 and 6624130.

📒 Files selected for processing (3)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go
  • packages/system/cozystack-workload-controller/api/v1alpha1/zz_generated.deepcopy.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)

🔇 Additional comments (1)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (1)

26-30: RBAC permissions are well-defined

The RBAC annotations follow best practices with proper separation of concerns and least privilege principle.

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/utils/pointer"

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.

🛠️ Refactor suggestion

Update deprecated package import

The k8s.io/utils/pointer package is deprecated. Please use k8s.io/utils/ptr instead.

Apply this diff to update the import:

-	"k8s.io/utils/pointer"
+	"k8s.io/utils/ptr"

Then update the usage in the code:

  • Replace pointer.Bool() with ptr.To()
📝 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
"k8s.io/utils/pointer"
"k8s.io/utils/ptr"
🧰 Tools
🪛 golangci-lint (1.62.2)

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)

@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: 4

🧹 Nitpick comments (5)
packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloadmonitors.yaml (2)

67-70: Add validation for kind and type fields

Consider adding an enum validation for the kind and type fields to restrict their values to a predefined set. This would prevent typos and ensure consistency.

Example values from PR description:

  • kind: "redis"
  • type: "redis" or "sentinel"
              kind:
                description: Kind specifies the kind of the workload
+               enum: ["redis"]
                type: string
              type:
                description: Type specifies the type of the workload
+               enum: ["redis", "sentinel"]
                type: string

Also applies to: 89-90


83-87: Consider adding validation for selector labels

The selector is a critical field that determines which pods are monitored. Consider adding validation to ensure that required labels are present.

Based on the PR description, the following labels should be required:

  • workload.cozystack.io/kind
  • workload.cozystack.io/type
              selector:
                additionalProperties:
                  type: string
                description: Selector is a label selector to find workloads to monitor
+               required: ["workload.cozystack.io/kind", "workload.cozystack.io/type"]
                type: object
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (3)

68-84: Improve error handling for resource annotation parsing

The current implementation continues silently when encountering parsing errors. Consider:

  1. Adding metrics/events for tracking parsing failures
  2. Logging the invalid annotation value for debugging
  3. Adding validation for resource types
   if resourcesStr, ok := pod.Annotations["workload.cozystack.io/resources"]; ok {
     annRes := map[string]string{}
     if err := json.Unmarshal([]byte(resourcesStr), &annRes); err != nil {
-      logger.Error(err, "Failed to parse resources annotation", "pod", pod.Name)
+      logger.Error(err, "Failed to parse resources annotation",
+        "pod", pod.Name,
+        "annotation", resourcesStr)
+      // Record metric for annotation parsing failure
+      metrics.RecordAnnotationParseFailure(pod.Name)
       // we do not return an error here to keep reconciling other Pods
     } else {
       for k, v := range annRes {
+        // Validate resource type
+        if !isValidResourceType(k) {
+          logger.Error(nil, "Invalid resource type in annotation",
+            "pod", pod.Name,
+            "resource", k)
+          continue
+        }
         parsed, err := resource.ParseQuantity(v)

179-184: Remove commented code for status update

The code contains commented-out implementation for status update using MergeFrom. Either:

  1. Remove the commented code if it's no longer needed
  2. Use the commented implementation if it's more appropriate than the current Update call

208-213: Improve error handling in Pod watch mapping

The current implementation silently returns nil when WorkloadMonitor listing fails. Consider:

  1. Logging the error with appropriate context
  2. Adding metrics for tracking listing failures
  3. Implementing retries for transient errors
   var monitorList cozyv1alpha1.WorkloadMonitorList
   if err := r.List(ctx, &monitorList, client.InNamespace(pod.Namespace)); err != nil {
-    // if we can't list, we can't do any mapping
+    // Log error with context
+    log.FromContext(ctx).Error(err, "Failed to list WorkloadMonitors",
+      "namespace", pod.Namespace,
+      "pod", pod.Name)
+    // Record metric for listing failure
+    metrics.RecordListFailure("workloadmonitors")
     return nil
   }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6624130 and 13812cf.

📒 Files selected for processing (9)
  • packages/apps/kubernetes/images/cluster-autoscaler.tag (1 hunks)
  • packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile (1 hunks)
  • packages/apps/kubernetes/images/cluster-autoscaler/fix-downscale.diff (1 hunks)
  • packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go (1 hunks)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/config/crd/bases/cozystack.io_workloadmonitors.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml (1 hunks)
  • packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/apps/kubernetes/images/cluster-autoscaler.tag
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/system/cozystack-workload-controller/config/rbac/role.yaml
  • packages/system/cozystack-workload-controller/api/v1alpha1/workloadmonitor_types.go
  • packages/system/cozystack-workload-controller/cmd/main.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)

🔇 Additional comments (6)
packages/apps/kubernetes/images/cluster-autoscaler/Dockerfile (1)

7-7: Verify cluster-autoscaler version compatibility

The upgrade from version 1.31.0 to 1.32.0 needs verification for compatibility with your Kubernetes cluster version.

packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (3)

10-10: Update deprecated package import

The k8s.io/utils/pointer package is deprecated. Use k8s.io/utils/ptr instead.

🧰 Tools
🪛 golangci-lint (1.62.2)

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)


173-177: 🛠️ Refactor suggestion

Use consistent pointer creation method

Replace pointer.Bool() with ptr.To() for consistency with the updated package import.

-  monitor.Status.Operational = pointer.Bool(true)
+  monitor.Status.Operational = ptr.To(true)

   if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas {
-    monitor.Status.Operational = pointer.Bool(false)
+    monitor.Status.Operational = ptr.To(false)
   }

Likely invalid or redundant comment.


160-164: Clarify error handling strategy

The code contains a comment "continue or return depending on your logic" but currently always continues. Consider:

  1. Documenting the rationale for continuing on errors
  2. Adding metrics/events for tracking reconciliation failures
  3. Implementing a maximum failure threshold
✅ Verification successful

Document current error handling strategy and add observability

The current strategy of continuing on pod reconciliation errors is correct as it ensures maximum visibility of workload state, but needs:

  1. Replace the comment "continue or return depending on your logic" with:
// Continue processing other pods to ensure maximum visibility of workload state.
// Individual pod failures are logged but don't block monitoring of remaining pods.
continue
  1. Consider adding metrics for failed reconciliations using the controller-runtime metrics framework (https://book.kubebuilder.io/reference/metrics.html)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any existing error handling patterns in the codebase
rg -A 5 "Failed to reconcile" --type go

Length of output: 809


Script:

#!/bin/bash
# Get the broader context of the reconciliation function
ast-grep --pattern 'func ($r $_) reconcilePodForMonitor($ctx, $monitor, $pod) error {
  $$$
}'

# Check for metrics/events related code
rg "metrics\." --type go packages/system/cozystack-workload-controller
rg "record\." --type go packages/system/cozystack-workload-controller

# Look for other error handling patterns
rg "return (fmt\.Errorf|err)" --type go packages/system/cozystack-workload-controller

Length of output: 1683


Script:

#!/bin/bash
# Get the complete controller file
cat packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go

Length of output: 8347

packages/apps/kubernetes/images/cluster-autoscaler/fix-downscale.diff (1)

9-10: ⚠️ Potential issue

Reconsider removing the maximum size constraint.

Removing the maximum size check from SetSize could lead to uncontrolled scaling and potential resource exhaustion. This change might:

  1. Allow scaling beyond infrastructure capacity
  2. Lead to unexpected costs
  3. Impact cluster stability

Consider keeping the max size check or implementing alternative safeguards.

Let's verify if there are other safeguards in place:

packages/apps/kubernetes/templates/cluster-autoscaler/deployment.yaml (1)

33-35: Verify impact of ignoring DaemonSets and mirror pods.

The configuration ignores both DaemonSet and mirror pod utilization:

- --ignore-daemonsets-utilization=true
- --ignore-mirror-pods-utilization=true

This could lead to inaccurate resource calculations if these pods consume significant resources.

Let's analyze the potential impact:

✅ Verification successful

DaemonSet and mirror pod utilization configuration is correct

The configuration to ignore DaemonSet and mirror pod utilization is actually the recommended setup for cluster-autoscaler. These pods represent mandatory system workloads that run on every node, so excluding them from resource calculations leads to more accurate scaling decisions based on actual user workload demands.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for DaemonSets and their resource requests
rg -A 10 "kind:\s+DaemonSet" "packages/apps/kubernetes/templates/" | rg "resources:"

# Look for mirror pod configurations
rg "annotations.*kubernetes.io/config.mirror" "packages/apps/kubernetes/templates/"

Length of output: 166


Script:

#!/bin/bash
# Search for DaemonSets across all yaml/yml files
fd -e yaml -e yml -x rg -l "kind:\s*DaemonSet" {}

# Search for resource specifications in those files
fd -e yaml -e yml -x rg -l "resources:" {}

# Look for documentation about these settings
rg -i "ignore.*daemonset|ignore.*mirror" -g "*.md"

# Check cluster-autoscaler documentation
fd -g "README*" -g "*.md" -x rg -l "cluster-autoscaler|autoscaling" {}

Length of output: 32675

@@ -1,12 +1,14 @@
# Source: https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/cluster-autoscaler/Dockerfile.amd64
ARG builder_image=docker.io/library/golang:1.22.5
ARG builder_image=docker.io/library/golang:1.23.4

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

Invalid Go version specified

The specified Go version 1.23.4 does not exist. As of January 2025, the latest stable version of Go is 1.22.0.

Please update to a valid Go version:

-ARG builder_image=docker.io/library/golang:1.23.4
+ARG builder_image=docker.io/library/golang:1.22.0
📝 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
ARG builder_image=docker.io/library/golang:1.23.4
ARG builder_image=docker.io/library/golang:1.22.0

Comment on lines +10 to +11
COPY fix-downscale.diff /fix-downscale.diff
RUN git apply /fix-downscale.diff

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.

💡 Codebase verification

⚠️ Concerning patch that bypasses autoscaler safety limits

The patch removes a critical safety check that prevents scaling beyond the maximum size limit in the cluster-autoscaler. This is a significant modification that:

  • Allows unrestricted upscaling beyond configured limits
  • Could lead to unexpected resource provisioning and costs
  • Modifies core safety behavior without documentation

Please provide:

  1. Justification for removing this safety check
  2. Documentation of the specific issue this addresses
  3. Confirmation whether this has been discussed upstream
  4. Plan for proper resolution (e.g., upstream PR) instead of local patching
🔗 Analysis chain

Missing context for downscale patch

A patch file fix-downscale.diff is being applied but:

  1. The patch file is not included in the PR
  2. There's no documentation explaining what issue this patch addresses

Please provide:

  1. The contents of the patch file
  2. Documentation about the issue being fixed
  3. Whether this is a temporary fix or if there's an upstream PR
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if patch file exists and show its contents
if [ -f "packages/apps/kubernetes/images/cluster-autoscaler/fix-downscale.diff" ]; then
    echo "Patch file contents:"
    cat packages/apps/kubernetes/images/cluster-autoscaler/fix-downscale.diff
else
    echo "Patch file not found in the repository"
fi

# Search for related issues in upstream repository
echo "Related upstream issues:"
gh api search/issues -X GET -f q="repo:kubernetes/autoscaler is:issue downscale" --jq '.items[] | {title: .title, url: .html_url, state: .state}'

Length of output: 6139

Comment on lines +36 to +37
- --scale-down-unneeded-time=30s
- --scan-interval=25s

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.

🛠️ Refactor suggestion

Consider increasing timing intervals for better stability.

The current timing configurations are quite aggressive:

  • scan-interval=25s: Frequent scanning increases CPU usage
  • scale-down-unneeded-time=30s: Short grace period might cause thrashing

Recommend increasing these values to provide better stability and reduce resource usage.

-        - --scale-down-unneeded-time=30s
-        - --scan-interval=25s
+        - --scale-down-unneeded-time=5m
+        - --scan-interval=1m
📝 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
- --scale-down-unneeded-time=30s
- --scan-interval=25s
- --scale-down-unneeded-time=5m
- --scan-interval=1m

- --ignore-mirror-pods-utilization=true
- --scale-down-unneeded-time=30s
- --scan-interval=25s
- --force-delete-unregistered-nodes=true

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.

💡 Codebase verification

⚠️ Current autoscaler configuration poses significant operational risks

The force deletion of unregistered nodes combined with aggressive scaling settings (30s unneeded time) and missing safety delays could lead to:

  • Workload disruption due to insufficient time for pod termination
  • Data loss in stateful applications
  • Cascading scaling events

Recommended safety measures:

  • Add --max-graceful-termination-sec
  • Increase --scale-down-unneeded-time (recommended 10-20 minutes)
  • Add --scale-down-delay-after-add and --scale-down-delay-after-delete
  • Consider setting --force-delete-unregistered-nodes=false for production environments
🔗 Analysis chain

Evaluate the risks of force-deleting unregistered nodes.

The --force-delete-unregistered-nodes=true option could lead to data loss or service disruption if nodes become temporarily unregistered due to network issues or control plane problems.

Let's check if there are any related issues or discussions:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related discussions or known issues
gh issue list -R kubernetes/autoscaler -l "force-delete,node-deletion" --json number,title,state

# Check for force delete related errors in logs
rg "force.*delet|node.*unregister" "packages/apps/kubernetes/templates/"

Length of output: 291


Script:

#!/bin/bash
# Check for node draining and safety configurations
rg -A 5 -B 5 "force-delete-unregistered-nodes" packages/apps/kubernetes/templates/

# Look for related cluster-autoscaler configurations
rg "scale-down|node-deletion|unneeded-nodes|max-graceful|drain|eviction" packages/apps/kubernetes/templates/cluster-autoscaler/

# Check if there's any documentation
fd "README|docs" packages/apps/kubernetes/templates/cluster-autoscaler/

Length of output: 1729

@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: 0

🧹 Nitpick comments (2)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (2)

56-71: Consider using maps.Clone for resource initialization

Instead of manually copying resource quantities, consider using maps.Clone from the golang.org/x/exp/maps package for better maintainability.


208-210: Add error logging in mapping function

The List operation error in the mapping function is silently ignored. Consider logging the error to help with debugging.

 				if err := r.List(ctx, &monitorList, client.InNamespace(pod.Namespace)); err != nil {
+					log.FromContext(ctx).Error(err, "Failed to list WorkloadMonitors for Pod", "pod", pod.Name)
 					return nil
 				}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13812cf and 2e85b4c.

📒 Files selected for processing (1)
  • packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (1 hunks)
🧰 Additional context used
🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)

🔇 Additional comments (4)
packages/system/cozystack-workload-controller/internal/controller/workloadmonitor_controller.go (4)

10-10: Update deprecated package import

The k8s.io/utils/pointer package is deprecated. Please use k8s.io/utils/ptr instead.

🧰 Tools
🪛 golangci-lint (1.62.2)

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)


1-237: Overall implementation looks good!

The WorkloadMonitor controller implementation is well-structured and follows Kubernetes controller patterns. It properly handles workload monitoring, resource tracking, and status updates. The suggested improvements are minor and can be addressed in follow-up commits.

🧰 Tools
🪛 golangci-lint (1.62.2)

10-10: SA1019: "k8s.io/utils/pointer" is deprecated: Use functions in k8s.io/utils/ptr instead: ptr.To to obtain a pointer, ptr.Deref to dereference a pointer, ptr.Equal to compare dereferenced pointers.

(staticcheck)


177-180: 🛠️ Refactor suggestion

Update pointer.Bool usage and consider adding periodic reconciliation

Two suggestions:

  1. Replace pointer.Bool with ptr.To from k8s.io/utils/ptr
  2. Consider adding a periodic reconciliation interval to ensure workload status stays accurate even if events are missed
-	monitor.Status.Operational = pointer.Bool(true)
+	monitor.Status.Operational = ptr.To(true)
 	if monitor.Spec.MinReplicas != nil && availableReplicas < *monitor.Spec.MinReplicas {
-		monitor.Status.Operational = pointer.Bool(false)
+		monitor.Status.Operational = ptr.To(false)
 	}

And update the return statement:

-	return ctrl.Result{}, nil
+	return ctrl.Result{RequeueAfter: 5 * time.Minute}, nil

Likely invalid or redundant comment.


81-87: Add validation for negative resource quantities

When parsing resource quantities from annotations, validate that they are non-negative to prevent potential issues with resource allocation.

@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: 2

🧹 Nitpick comments (3)
packages/system/cozystack-workload-controller/internal/telemetry/collector.go (3)

161-172: Accurately group nodes by kernel version in metrics.

Currently, the cozy_nodes_count metric uses the kernel version from the first node for all entries, which may be inaccurate if nodes have different kernel versions. Modify the code to group nodes by both OS and kernel version.

Apply this diff to adjust the grouping:

-nodeOSCount := make(map[string]int)
+nodeMetrics := make(map[string]int)
 for _, node := range nodeList.Items {
     key := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage)
+    kernelVersion := node.Status.NodeInfo.KernelVersion
+    combinedKey := fmt.Sprintf("%s|%s", key, kernelVersion)
-    nodeOSCount[key] = nodeOSCount[key] + 1
+    nodeMetrics[combinedKey]++
 }

-for osKey, count := range nodeOSCount {
+for combinedKey, count := range nodeMetrics {
+    parts := strings.Split(combinedKey, "|")
+    osKey := parts[0]
+    kernelVersion := parts[1]
     metrics.WriteString(fmt.Sprintf(
         "cozy_nodes_count{os=\"%s\",kernel=\"%s\"} %d\n",
         osKey,
-        nodeList.Items[0].Status.NodeInfo.KernelVersion,
+        kernelVersion,
         count,
     ))
 }

This ensures that the metrics accurately reflect the node distribution across different kernel versions.


285-285: Handle error return value of resp.Body.Close().

The Close() method returns an error that should be checked to prevent potential resource leaks or unnoticed I/O errors.

Modify the code to handle the error:

 defer resp.Body.Close()
+defer func() {
+    if err := resp.Body.Close(); err != nil {
+        logger.Error(err, "Failed to close response body")
+    }
+}()
🧰 Tools
🪛 golangci-lint (1.62.2)

285-285: Error return value of resp.Body.Close is not checked

(errcheck)


111-269: Refactor the collect method for better maintainability.

The collect method is large and handles multiple responsibilities, making it harder to read and maintain. Consider breaking it into smaller, focused functions.

For example, extract the metric collection into separate methods:

  • func (c *Collector) collectClusterInfo(ctx context.Context) (string, error)
  • func (c *Collector) collectNodeMetrics(ctx context.Context) (string, error)
  • func (c *Collector) collectServiceMetrics(ctx context.Context) (string, error)
  • func (c *Collector) collectNamespaceMetrics(ctx context.Context) (string, error)
  • func (c *Collector) collectPVMetrics(ctx context.Context) (string, error)
  • func (c *Collector) collectWorkloadMetrics(ctx context.Context) (string, error)

Then, in the collect method, you can aggregate these metrics:

func (c *Collector) collect(ctx context.Context) {
    // ...
    var metrics strings.Builder

    clusterInfoMetrics, err := c.collectClusterInfo(ctx)
    if err != nil {
        logger.Error(err, "Failed to collect cluster info")
        return
    }
    metrics.WriteString(clusterInfoMetrics)

    nodeMetrics, err := c.collectNodeMetrics(ctx)
    // Handle error and append metrics similarly

    // Repeat for other metric types

    // Send metrics
    if err := c.sendMetrics(clusterID, metrics.String()); err != nil {
        logger.Error(err, "Failed to send metrics")
    }
}

This approach enhances readability and makes the codebase easier to maintain and test.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2e85b4c and c0aa103.

📒 Files selected for processing (3)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/telemetry/collector.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/telemetry/config.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/system/cozystack-workload-controller/cmd/main.go
🧰 Additional context used
🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/internal/telemetry/collector.go

285-285: Error return value of resp.Body.Close is not checked

(errcheck)

🔇 Additional comments (1)
packages/system/cozystack-workload-controller/internal/telemetry/config.go (1)

8-17: Configuration setup looks good.

The Config struct is well-defined with appropriate fields and documentation. The DefaultConfig function provides sensible defaults for telemetry configuration.

Comment on lines +148 to +155
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))

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

Correct typos in metric labels bunde_enable and bunde_disable.

In the cozy_cluster_info metric, the labels bunde_enable and bunde_disable are misspelled. They should be bundle_enable and bundle_disable to ensure consistency and avoid confusion.

Apply this diff to fix the typos:

 metrics.WriteString(fmt.Sprintf(
-    "cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
+    "cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bundle_enable=\"%s\",bundle_disable=\"%s\"} 1\n",
     c.config.CozystackVersion,
     k8sVersion,
     oidcEnabled,
     bundle,
     bundleEnable,
     bundleDisable,
 ))
📝 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
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bundle_enable=\"%s\",bundle_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))

Comment on lines +80 to +108
func getSizeGroup(size resource.Quantity) string {
gb := size.Value() / (1024 * 1024 * 1024)
switch {
case gb <= 1:
return "1Gi"
case gb <= 5:
return "5Gi"
case gb <= 10:
return "10Gi"
case gb <= 25:
return "25Gi"
case gb <= 50:
return "50Gi"
case gb <= 100:
return "100Gi"
case gb <= 250:
return "250Gi"
case gb <= 500:
return "500Gi"
case gb <= 1024:
return "1Ti"
case gb <= 2048:
return "2Ti"
case gb <= 5120:
return "5Ti"
default:
return "10Ti"
}
}

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.

🛠️ Refactor suggestion

Ensure accurate calculation of PV size groups.

The function getSizeGroup may produce incorrect size groupings due to integer division truncation when calculating gb. Using floating-point arithmetic or the AsApproximateFloat64() method provides a more accurate calculation.

Apply this diff to improve the calculation:

 func getSizeGroup(size resource.Quantity) string {
-    gb := size.Value() / (1024 * 1024 * 1024)
+    gb := size.AsApproximateFloat64() / (1 << 30)
     switch {
-    case gb <= 1:
+    case gb <= 1.0:
         return "1Gi"
-    case gb <= 5:
+    case gb <= 5.0:
         return "5Gi"
     // Update other cases similarly
     default:
         return "10Ti"
     }
 }

This change prevents misclassification of PV sizes due to rounding errors.

Committable suggestion skipped: line range outside the PR's diff.

@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: 1

🧹 Nitpick comments (4)
packages/system/cozystack-workload-controller/cmd/main.go (3)

1-2: Update the copyright year.

The copyright year 2025 is in the future. Consider updating it to the current year or removing the year entirely.

-Copyright 2025.
+Copyright 2024.

80-81: Consider making the telemetry endpoint configurable via environment variable.

The telemetry endpoint is hardcoded. Consider making it configurable via an environment variable to support different environments and testing scenarios.

-	flag.StringVar(&telemetryEndpoint, "telemetry-endpoint", "https://telemetry.cozystack.io",
+	flag.StringVar(&telemetryEndpoint, "telemetry-endpoint", getEnvOrDefault("TELEMETRY_ENDPOINT", "https://telemetry.cozystack.io"),

Add this helper function:

func getEnvOrDefault(key, defaultValue string) string {
    if value := os.Getenv(key); value != "" {
        return value
    }
    return defaultValue
}

199-202: Remove duplicate error logging.

The error is logged twice with different verbosity levels. Consider keeping only the verbose log since this is a non-critical component.

 		if err := mgr.Add(collector); err != nil {
-			setupLog.Error(err, "unable to set up telemetry collector")
 			setupLog.V(1).Error(err, "unable to set up telemetry collector, continuing without telemetry")
 		}
packages/system/cozystack-workload-controller/internal/telemetry/collector.go (1)

285-285: Handle error from resp.Body.Close().

The error returned by resp.Body.Close() should be checked to ensure proper resource cleanup.

-	defer resp.Body.Close()
+	defer func() {
+		if cerr := resp.Body.Close(); cerr != nil {
+			err = fmt.Errorf("failed to close response body: %v", cerr)
+		}
+	}()
🧰 Tools
🪛 golangci-lint (1.62.2)

285-285: Error return value of resp.Body.Close is not checked

(errcheck)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c0aa103 and 2ba9155.

📒 Files selected for processing (2)
  • packages/system/cozystack-workload-controller/cmd/main.go (1 hunks)
  • packages/system/cozystack-workload-controller/internal/telemetry/collector.go (1 hunks)
🧰 Additional context used
🪛 golangci-lint (1.62.2)
packages/system/cozystack-workload-controller/internal/telemetry/collector.go

285-285: Error return value of resp.Body.Close is not checked

(errcheck)

🔇 Additional comments (4)
packages/system/cozystack-workload-controller/cmd/main.go (2)

45-55: LGTM!

The scheme initialization is well-structured and follows Kubernetes controller best practices.


109-168: LGTM! Good security practices.

The implementation shows excellent security awareness by:

  • Disabling HTTP/2 by default to prevent vulnerabilities
  • Properly configuring TLS options
  • Including comprehensive documentation about security implications
packages/system/cozystack-workload-controller/internal/telemetry/collector.go (2)

80-108: Ensure accurate calculation of PV size groups.

The integer division in size calculation may lead to incorrect grouping due to truncation.


148-155: Correct typos in metric labels bunde_enable and bunde_disable.

Comment on lines +75 to +77
func (c *Collector) Stop() {
close(c.stopCh)
}

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.

🛠️ Refactor suggestion

Protect against potential race condition in Stop method.

The Stop method might be called concurrently with Start, leading to a potential race condition when closing the channel. Consider adding a mutex to protect the channel operations.

 type Collector struct {
 	client          client.Client
 	discoveryClient discovery.DiscoveryInterface
 	config          *Config
 	ticker          *time.Ticker
 	stopCh          chan struct{}
+	mu              sync.Mutex
 }

 func (c *Collector) Stop() {
+	c.mu.Lock()
+	defer c.mu.Unlock()
+	if c.stopCh != nil {
 		close(c.stopCh)
+		c.stopCh = nil
+	}
 }

Committable suggestion skipped: line range outside the PR's diff.

@kvaps Andrei Kvapil (kvaps) changed the title add workload-controller Introduce cozystack-controller Jan 8, 2025

@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: 22

🧹 Nitpick comments (19)
api/v1alpha1/groupversion_info.go (2)

17-20: Consider enhancing the package documentation.

While the current documentation is functional, it could be more descriptive about the purpose and contents of this API group. Consider adding information about:

  • The types of resources defined in this group
  • The intended use cases
  • Any specific constraints or requirements

27-36: LGTM! Consider documenting API versioning strategy.

The API group version definitions are well-structured and follow Kubernetes conventions. Since this is an alpha API (v1alpha1), consider documenting:

  • The API stability guarantees
  • The planned timeline for beta/stable releases
  • Breaking changes that might be introduced in future versions
cmd/cozystack-controller/main.go (2)

167-168: Evaluate enabling LeaderElectionReleaseOnCancel for faster leader transitions

The LeaderElectionReleaseOnCancel option is currently commented out. Enabling this option allows the leader to step down voluntarily when the manager stops, speeding up leader transitions. If your application doesn't perform operations after the manager stops, it is safe to enable this option.


195-201: Ensure consistent logging levels for telemetry collector errors

The error logging for the telemetry collector setup uses different verbosity levels. At line 195, the error is logged with setupLog.V(1).Error(...), while at line 200, it's logged with setupLog.Error(...). For consistency and to ensure critical errors are appropriately captured, consider using the same logging level for similar error messages.

api/v1alpha1/workload_types.go (1)

37-37: Consider restricting resource types in the Resources map.

The Resources map allows any string key, which might lead to inconsistencies. Consider using a more structured approach with predefined resource types.

-	Resources map[string]resource.Quantity `json:"resources"`
+	Resources ResourceRequirements `json:"resources"`

+// ResourceRequirements defines compute resource requirements
+type ResourceRequirements struct {
+	CPU    resource.Quantity `json:"cpu"`
+	Memory resource.Quantity `json:"memory"`
+}
api/v1alpha1/zz_generated.deepcopy.go (1)

4-4: Update the copyright year to 2024

The copyright year is set to 2025, which is in the future. This should be updated to the current year.

-Copyright 2025 The Cozystack Authors.
+Copyright 2024 The Cozystack Authors.
packages/system/cozystack-controller/.github/workflows/test.yml (1)

20-23: Optimize CI performance and add test coverage reporting

Consider these improvements:

  1. Add Go modules caching to speed up CI runs
  2. Add test coverage reporting for better visibility into test quality
      - name: Running Tests
        run: |
          go mod tidy
-         make test
+         go mod download
+         make test
+         go test -race -coverprofile=coverage.txt -covermode=atomic ./...
+      
+      - name: Upload coverage to Codecov
+        uses: codecov/codecov-action@v4
+        with:
+          file: ./coverage.txt
packages/system/cozystack-controller/.github/workflows/lint.yml (1)

20-23: Enhance linter configuration

Consider these improvements:

  1. Add a timeout to prevent long-running lints
  2. Specify a golangci-lint configuration file
      - name: Run linter
        uses: golangci/golangci-lint-action@v6
        with:
          version: v1.61
+         args: --timeout=5m
+         config-path: .golangci.yml
packages/system/cozystack-controller/.github/workflows/test-e2e.yml (2)

20-24: Pin the kind version for reproducible builds

Currently using the latest version of kind could lead to inconsistent test environments. Consider pinning to a specific version.

-curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
+curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-linux-amd64

32-35: Add timeout and artifact collection for E2E tests

Consider:

  1. Adding a timeout for the E2E tests to prevent hung tests from blocking CI
  2. Collecting and uploading test logs and results as artifacts
       - name: Running Test e2e
+        timeout-minutes: 30
         run: |
           go mod tidy
           make test-e2e
+          
+      - name: Upload test results
+        if: always()
+        uses: actions/upload-artifact@v3
+        with:
+          name: e2e-test-results
+          path: |
+            ./test-results/
+            ./logs/
packages/system/cozystack-controller/Makefile (1)

7-7: Add .PHONY declarations for make targets

Declare targets as .PHONY to prevent conflicts with files of the same name and improve make's performance.

+.PHONY: image image-cozystack-controller

 image: image-cozystack-controller

 image-cozystack-controller:

Also applies to: 9-10

packages/system/cozystack-controller/.golangci.yml (2)

21-43: Consider additional security and best practice linters

The current linter configuration could be enhanced with:

  1. gosec for security checks
  2. gocritic for advanced style checks
  3. nolintlint to ensure proper placement of nolint directives
   enable:
     - dupl
     - errcheck
     - copyloopvar
     - ginkgolinter
     - goconst
     - gocyclo
     - gofmt
     - goimports
     - gosimple
     - govet
     - ineffassign
     - lll
     - misspell
     - nakedret
     - prealloc
     - revive
     - staticcheck
     - typecheck
     - unconvert
     - unparam
     - unused
+    - gosec
+    - gocritic
+    - nolintlint

44-47: Complete the revive rule configuration

The comment-spacings rule lacks specific configuration parameters.

 linters-settings:
   revive:
     rules:
       - name: comment-spacings
+        arguments:
+          - always
+        severity: warning
Makefile (1)

41-42: Document the generate target and add dependencies

The generate target should document its purpose and specify any required dependencies.

+# generate - Runs code generation for controller-gen artifacts
+.PHONY: generate
+generate: ## Generate controller-gen artifacts (CRDs, RBAC)
+generate: manifests
 generate:
 	hack/update-codegen.sh
hack/update-codegen.sh (2)

51-52: Add validation for generated artifacts

Consider adding validation steps after generation to ensure the output is as expected.

 $CONTROLLER_GEN object:headerFile="hack/boilerplate.go.txt" paths="./api/..."
 $CONTROLLER_GEN rbac:roleName=manager-role crd paths="./api/..." output:crd:artifacts:config=packages/system/cozystack-controller/templates/crds
+
+# Validate generated CRDs
+echo "Validating generated CRDs..."
+for crd in packages/system/cozystack-controller/templates/crds/*.yaml; do
+  if ! kubectl explain --schema-path="$crd" >/dev/null 2>&1; then
+    echo "Error validating CRD: $crd"
+    exit 1
+  fi
+done

25-25: Consider making controller-gen version configurable

The controller-gen version could be made configurable via an environment variable.

-CONTROLLER_GEN="go run sigs.k8s.io/controller-tools/cmd/controller-gen@v0.16.4"
+CONTROLLER_GEN_VERSION="${CONTROLLER_GEN_VERSION:-v0.16.4}"
+CONTROLLER_GEN="go run sigs.k8s.io/controller-tools/cmd/controller-gen@${CONTROLLER_GEN_VERSION}"
packages/system/cozystack-controller/templates/crds/cozystack.io_workloads.yaml (2)

34-85: Add validation for resource field names

The resources field in status allows any property name. Consider adding an enum or pattern to validate common resource types (cpu, memory) to prevent typos and ensure consistency.

               resources:
                 additionalProperties:
                   anyOf:
                   - type: integer
                   - type: string
                   pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
                   x-kubernetes-int-or-string: true
                 description: Resources specifies the compute resources allocated to
                   this workload
+                properties:
+                  cpu:
+                    x-kubernetes-int-or-string: true
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
+                  memory:
+                    x-kubernetes-int-or-string: true
+                    pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
                 type: object

1-88: Consider adding spec section for future extensibility

The CRD only defines status fields without any spec section. While this might work for the current use case of monitoring workloads, consider adding a spec section for future extensibility (e.g., monitoring configuration, thresholds).

packages/system/cozystack-controller/templates/crds/cozystack.io_workloadmonitors.yaml (1)

91-94: Add pattern validation for version field

The version field should follow semantic versioning pattern to ensure consistency.

               version:
                 description: Version specifies the version of the workload
+                pattern: ^v?\d+\.\d+\.\d+(-[\w.]+)?$
                 type: string
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2ba9155 and eb264e1.

⛔ Files ignored due to path filters (5)
  • go.sum is excluded by !**/*.sum
  • pkg/generated/applyconfiguration/apps/v1alpha1/application.go is excluded by !**/generated/**
  • pkg/generated/applyconfiguration/utils.go is excluded by !**/generated/**
  • pkg/generated/listers/apps/v1alpha1/application.go is excluded by !**/generated/**
  • pkg/generated/openapi/zz_generated.openapi.go is excluded by !**/generated/**
📒 Files selected for processing (48)
  • Makefile (1 hunks)
  • api/api-rules/cozystack_api_violation_exceptions.list (1 hunks)
  • api/v1alpha1/groupversion_info.go (1 hunks)
  • api/v1alpha1/workload_types.go (1 hunks)
  • api/v1alpha1/workloadmonitor_types.go (1 hunks)
  • api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • cmd/cozystack-api/main.go (1 hunks)
  • cmd/cozystack-controller/main.go (1 hunks)
  • go.mod (3 hunks)
  • hack/boilerplate.go.txt (1 hunks)
  • hack/update-codegen.sh (2 hunks)
  • internal/controller/suite_test.go (1 hunks)
  • internal/controller/workloadmonitor_controller.go (1 hunks)
  • internal/telemetry/collector.go (1 hunks)
  • internal/telemetry/config.go (1 hunks)
  • packages/system/cozystack-api/images/cozystack-api/Dockerfile (2 hunks)
  • packages/system/cozystack-controller/.devcontainer/devcontainer.json (1 hunks)
  • packages/system/cozystack-controller/.devcontainer/post-install.sh (1 hunks)
  • packages/system/cozystack-controller/.dockerignore (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/lint.yml (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/test-e2e.yml (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/test.yml (1 hunks)
  • packages/system/cozystack-controller/.gitignore (1 hunks)
  • packages/system/cozystack-controller/.golangci.yml (1 hunks)
  • packages/system/cozystack-controller/Chart.yaml (1 hunks)
  • packages/system/cozystack-controller/Makefile (1 hunks)
  • packages/system/cozystack-controller/images/cozystack-controller/Dockerfile (1 hunks)
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloadmonitors.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloads.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/deployment.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/rbac-bind.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/rbac.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/sa.yaml (1 hunks)
  • packages/system/cozystack-controller/values.yaml (1 hunks)
  • pkg/apis/apps/fuzzer/fuzzer.go (1 hunks)
  • pkg/apis/apps/install/install.go (1 hunks)
  • pkg/apis/apps/install/roundtrip_test.go (1 hunks)
  • pkg/apis/apps/v1alpha1/doc.go (1 hunks)
  • pkg/apis/apps/v1alpha1/register.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.conversion.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.defaults.go (1 hunks)
  • pkg/apis/apps/validation/validation.go (1 hunks)
  • pkg/apiserver/apiserver.go (1 hunks)
  • pkg/apiserver/scheme_test.go (1 hunks)
  • pkg/cmd/server/start.go (1 hunks)
  • pkg/registry/apps/application/rest.go (1 hunks)
  • pkg/registry/registry.go (1 hunks)
✅ Files skipped from review due to trivial changes (22)
  • hack/boilerplate.go.txt
  • pkg/apis/apps/v1alpha1/zz_generated.conversion.go
  • pkg/apis/apps/v1alpha1/zz_generated.defaults.go
  • packages/system/cozystack-controller/.dockerignore
  • packages/system/cozystack-controller/templates/sa.yaml
  • packages/system/cozystack-controller/Chart.yaml
  • pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go
  • pkg/registry/registry.go
  • pkg/apis/apps/validation/validation.go
  • packages/system/cozystack-controller/values.yaml
  • pkg/apis/apps/install/roundtrip_test.go
  • packages/system/cozystack-controller/.gitignore
  • cmd/cozystack-api/main.go
  • pkg/registry/apps/application/rest.go
  • pkg/apis/apps/fuzzer/fuzzer.go
  • api/api-rules/cozystack_api_violation_exceptions.list
  • pkg/apis/apps/install/install.go
  • pkg/apiserver/apiserver.go
  • pkg/apis/apps/v1alpha1/register.go
  • pkg/apis/apps/v1alpha1/doc.go
  • pkg/cmd/server/start.go
  • packages/system/cozystack-controller/.devcontainer/devcontainer.json
🧰 Additional context used
🪛 golangci-lint (1.62.2)
pkg/apiserver/scheme_test.go

22-22: could not import github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer (-: # github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer
pkg/apis/apps/fuzzer/fuzzer.go:29:16: undefined: apps.ApplicationSpec)

(typecheck)

🔇 Additional comments (11)
pkg/apiserver/scheme_test.go (1)

22-22: Verify import path changes across the codebase

The import path change from aenix.io to aenix-io appears to be part of a broader correction. Let's verify this change is consistent across all files.

✅ Verification successful

Import path changes are consistent across the codebase

All Go files in the repository consistently use the new import path format github.com/aenix-io/cozystack. The change in pkg/apiserver/scheme_test.go aligns with the repository-wide pattern.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining instances of the old import path
rg "github.com/aenix\.io/cozystack" --type go

# List all Go files that might need the import path updated
fd -e go | xargs grep -l "github.com/aenix"

Length of output: 818


Script:

#!/bin/bash
# Show the actual import lines containing aenix from all Go files
rg "^import.*github.com/aenix" --type go -B 1 -A 1

# Also check for specific import statements to see the exact format
rg "github.com/aenix[.-]io/cozystack" --type go

Length of output: 4395

🧰 Tools
🪛 golangci-lint (1.62.2)

22-22: could not import github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer (-: # github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer
pkg/apis/apps/fuzzer/fuzzer.go:29:16: undefined: apps.ApplicationSpec)

(typecheck)

api/v1alpha1/groupversion_info.go (3)

1-15: LGTM! Standard Apache 2.0 license header with correct copyright year.


22-25: LGTM! Appropriate imports for API group version definition.


27-36: Verify WorkloadMonitor CRD integration.

Let's verify that the WorkloadMonitor CRD is properly configured to use this API group version.

✅ Verification successful

WorkloadMonitor CRD integration verified successfully.

The CRD is properly configured to use the cozystack.io/v1alpha1 API group version and all components are correctly integrated.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify WorkloadMonitor CRD configuration

# Check if WorkloadMonitor CRD exists and uses the correct API group version
rg -l "kind:\s+CustomResourceDefinition" | xargs rg "cozystack.io/v1alpha1.*workloadmonitor" -A 5

# Check for any other resources using this API group version
rg "apiVersion:\s+cozystack.io/v1alpha1" -A 2

Length of output: 570


Script:

#!/bin/bash
# Search for WorkloadMonitor CRD definition
fd -e yaml -e yml | xargs rg "kind:\s+CustomResourceDefinition" -A 5 -B 2

# Search for any Go type definitions related to WorkloadMonitor
ast-grep --pattern 'type WorkloadMonitor struct {
  $$$
}'

Length of output: 66616


Script:

#!/bin/bash
# Search for WorkloadMonitor in YAML/YML files
fd -e yaml -e yml | xargs rg "kind:\s+WorkloadMonitor" -B 2 -A 2

# Search for WorkloadMonitor CRD definition
fd -e yaml -e yml | xargs rg "name:\s+workloadmonitors?.cozystack.io" -B 2 -A 2

# Search for Go files containing WorkloadMonitor type
fd -e go | xargs rg "type\s+WorkloadMonitor\s+struct" -A 5

Length of output: 2483

internal/telemetry/collector.go (1)

81-85: Verify correct size grouping for PersistentVolumeClaims smaller than 1Gi

The calculation of gb uses integer division, which results in gb being zero for sizes less than 1Gi. This means that PVCs smaller than 1Gi are grouped under "1Gi" since gb <= 1 will be true. If this is intentional, no action is needed. Otherwise, consider using floating-point division to more precisely group smaller sizes.

api/v1alpha1/zz_generated.deepcopy.go (1)

19-20: LGTM! Auto-generated code verified.

This file is auto-generated by controller-gen and implements the required deepcopy functions for the new CRD types. The implementations follow the standard Kubernetes patterns for deep copying objects.

packages/system/cozystack-controller/templates/rbac-bind.yaml (1)

1-12: LGTM! RBAC binding is properly configured.

The ClusterRoleBinding correctly associates the cozystack-controller ClusterRole with the ServiceAccount in the cozy-system namespace, following Kubernetes RBAC best practices.

packages/system/cozystack-api/images/cozystack-api/Dockerfile (1)

11-11: LGTM! Directory structure maintained.

The addition of the internal directory copy maintains the correct module structure.

packages/system/cozystack-controller/Makefile (1)

18-19: Pin yq version for reproducible builds

The yq tool version should be pinned to ensure consistent behavior across different environments.

packages/system/cozystack-controller/templates/crds/cozystack.io_workloadmonitors.yaml (1)

67-90: Consider making kind and type required fields

The kind and type fields are optional but seem essential for proper workload monitoring. Consider making them required fields or clarify in the description why they're optional.

Let's check if there are any workload monitors without these fields:

go.mod (1)

8-24: LGTM on dependencies

The Kubernetes-related dependencies and testing frameworks are properly versioned and aligned with the controller-runtime version.

"testing"

appsfuzzer "github.com/aenix.io/cozystack/pkg/apis/apps/fuzzer"
appsfuzzer "github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer"

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

Fix build failure in fuzzer package

The static analysis indicates that apps.ApplicationSpec is undefined in the fuzzer package. This suggests that either:

  1. The apps package is missing required type definitions
  2. The import path change has broken dependencies

Please verify that:

  1. The apps.ApplicationSpec type is properly defined
  2. All dependent packages are updated with the new import path
  3. The module path in go.mod matches the new repository path

Run this script to investigate the issue:

#!/bin/bash
# Check for ApplicationSpec definition
ast-grep --pattern 'type ApplicationSpec struct {
  $$$
}'

# Verify module path in go.mod
grep "module" go.mod
🧰 Tools
🪛 golangci-lint (1.62.2)

22-22: could not import github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer (-: # github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer
pkg/apis/apps/fuzzer/fuzzer.go:29:16: undefined: apps.ApplicationSpec)

(typecheck)

Comment on lines +145 to +148
// TODO(user): If CertDir, CertName, and KeyName are not specified, controller-runtime will automatically
// generate self-signed certificates for the metrics server. While convenient for development and testing,
// this setup is not recommended for production.
}

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.

🛠️ Refactor suggestion

Consider configuring custom TLS certificates for production environments

The metrics server currently relies on automatically generated self-signed certificates when CertDir, CertName, and KeyName are not specified. While this setup is convenient for development and testing, it's not recommended for production due to security concerns. Please consider configuring appropriate TLS certificates to enhance security in production deployments.

Do you want me to provide guidance on configuring the metrics server with custom TLS certificates or open a new GitHub issue to track this task?

Comment on lines +148 to +155
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))

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

Fix typos in metric labels bunde_enable and bunde_disable

In the metrics output, the labels bunde_enable and bunde_disable appear to be misspelled. They should likely be bundle_enable and bundle_disable. Typos in metric labels can lead to issues with metric collection and querying.

Apply this diff to correct the typos:

-    			"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
+    			"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bundle_enable=\"%s\",bundle_disable=\"%s\"} 1\n",
📝 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
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))
"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bundle_enable=\"%s\",bundle_disable=\"%s\"} 1\n",
c.config.CozystackVersion,
k8sVersion,
oidcEnabled,
bundle,
bundleEnable,
bundleDisable,
))

Comment on lines +165 to +172
for osKey, count := range nodeOSCount {
metrics.WriteString(fmt.Sprintf(
"cozy_nodes_count{os=\"%s\",kernel=\"%s\"} %d\n",
osKey,
nodeList.Items[0].Status.NodeInfo.KernelVersion,
count,
))
}

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

Accurately report kernel versions in node metrics

The current implementation uses nodeList.Items[0].Status.NodeInfo.KernelVersion for all nodes when populating the kernel label in cozy_nodes_count. This assumes all nodes share the same kernel version, which may not be the case. Consider grouping nodes by both OS and kernel version to reflect the actual distribution accurately.

Modify the code to aggregate nodes by both operating system and kernel version:

-	for _, node := range nodeList.Items {
-		key := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage)
-		nodeOSCount[key] = nodeOSCount[key] + 1
-	}
+	for _, node := range nodeList.Items {
+		key := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage)
+		kernelVersion := node.Status.NodeInfo.KernelVersion
+		nodeOSCount[key][kernelVersion]++
+	}

Update the metrics writing section accordingly to include kernel version per node group.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +199 to +232
&corev1.Pod{},
handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, obj client.Object) []reconcile.Request {
pod, ok := obj.(*corev1.Pod)
if !ok {
return nil
}

var monitorList cozyv1alpha1.WorkloadMonitorList
// List all WorkloadMonitors in the same namespace
if err := r.List(ctx, &monitorList, client.InNamespace(pod.Namespace)); err != nil {
return nil
}

// Match each monitor's selector with the Pod's labels
var requests []reconcile.Request
for _, m := range monitorList.Items {
matches := true
for k, v := range m.Spec.Selector {
if podVal, exists := pod.Labels[k]; !exists || podVal != v {
matches = false
break
}
}
if matches {
requests = append(requests, reconcile.Request{
NamespacedName: types.NamespacedName{
Namespace: m.Namespace,
Name: m.Name,
},
})
}
}
return requests
}),

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.

🛠️ Refactor suggestion

Optimize Pod to WorkloadMonitor mapping for scalability

In the SetupWithManager method, the mapping function for Pod events lists all WorkloadMonitor resources in the namespace and checks each one for matching selectors. This approach may become a performance bottleneck in namespaces with many WorkloadMonitor objects. Consider using an indexer to map Pods to WorkloadMonitor resources efficiently.

You can set up an index on the WorkloadMonitor selectors and use it to quickly find relevant monitors for a given Pod.

Comment on lines +4 to +6
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

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

Add checksum verification for downloaded binaries

Currently downloading binaries without verifying their checksums poses a security risk.

+# Download and verify kind
 curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
+curl -Lo ./kind.sha256 https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64.sha256
+echo "$(<kind.sha256) kind" | sha256sum --check
 chmod +x ./kind
 mv ./kind /usr/local/bin/kind
📝 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
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind
# Download and verify kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
curl -Lo ./kind.sha256 https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64.sha256
echo "$(<kind.sha256) kind" | sha256sum --check
chmod +x ./kind
mv ./kind /usr/local/bin/kind

Comment on lines +1 to +23
#!/bin/bash
set -x

curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
mv ./kind /usr/local/bin/kind

curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64
chmod +x kubebuilder
mv kubebuilder /usr/local/bin/

KUBECTL_VERSION=$(curl -L -s https://dl.k8s.io/release/stable.txt)
curl -LO "https://dl.k8s.io/release/$KUBECTL_VERSION/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/kubectl

docker network create -d=bridge --subnet=172.19.0.0/24 kind

kind version
kubebuilder version
docker --version
go version
kubectl version --client

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.

🛠️ Refactor suggestion

Add error handling and improve network creation

The script needs better error handling and should handle existing Docker networks gracefully.

 #!/bin/bash
-set -x
+set -euo pipefail
+
+# Error handler
+trap 'echo "Error on line $LINENO"' ERR
+
+# Create network if it doesn't exist
+if ! docker network inspect kind >/dev/null 2>&1; then
+  docker network create -d=bridge --subnet=172.19.0.0/24 kind
+fi
 
+# Function to safely install a binary
+install_binary() {
+  local name=$1
+  local url=$2
+  local dest="/usr/local/bin/$name"
+  
+  echo "Installing $name..."
+  if ! curl -sSLf -o "/tmp/$name" "$url"; then
+    echo "Failed to download $name"
+    return 1
+  fi
+  chmod +x "/tmp/$name"
+  mv "/tmp/$name" "$dest"
+}
+
+# Install binaries
+install_binary "kind" "https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64"
+install_binary "kubebuilder" "https://go.kubebuilder.io/dl/latest/linux/amd64"
 
-docker network create -d=bridge --subnet=172.19.0.0/24 kind
+# Print versions
+echo "Installed versions:"
+kind version
+kubebuilder version
+docker --version
+go version
+kubectl version --client

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +86 to +88
served: true
storage: true
subresources: {}

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.

🛠️ Refactor suggestion

Enable status subresource

The CRD should enable the status subresource to follow Kubernetes conventions for resources with status fields.

     served: true
     storage: true
-    subresources: {}
+    subresources:
+      status: {}
📝 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
served: true
storage: true
subresources: {}
served: true
storage: true
subresources:
status: {}

Comment on lines +70 to +82
minReplicas:
description: MinReplicas specifies the minimum number of replicas
that should be available
format: int32
minimum: 0
type: integer
replicas:
description: |-
Replicas is the desired number of replicas
If not specified, will use observedReplicas as the target
format: int32
minimum: 0
type: integer

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.

🛠️ Refactor suggestion

Add cross-field validation for replicas

Add validation to ensure that minReplicas is not greater than replicas when both are specified.

               minReplicas:
                 description: MinReplicas specifies the minimum number of replicas
                   that should be available
                 format: int32
                 minimum: 0
                 type: integer
               replicas:
                 description: |-
                   Replicas is the desired number of replicas
                   If not specified, will use observedReplicas as the target
                 format: int32
                 minimum: 0
                 type: integer
+              x-kubernetes-validations:
+              - rule: "self.replicas == nil || self.minReplicas <= self.replicas"
+                message: "minReplicas must not be greater than replicas"
📝 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
minReplicas:
description: MinReplicas specifies the minimum number of replicas
that should be available
format: int32
minimum: 0
type: integer
replicas:
description: |-
Replicas is the desired number of replicas
If not specified, will use observedReplicas as the target
format: int32
minimum: 0
type: integer
minReplicas:
description: MinReplicas specifies the minimum number of replicas
that should be available
format: int32
minimum: 0
type: integer
replicas:
description: |-
Replicas is the desired number of replicas
If not specified, will use observedReplicas as the target
format: int32
minimum: 0
type: integer
x-kubernetes-validations:
- rule: "self.replicas == nil || self.minReplicas <= self.replicas"
message: "minReplicas must not be greater than replicas"

Comment thread go.mod
Comment on lines +3 to 5
module github.com/aenix-io/cozystack

go 1.23.0

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

Fix invalid Go version

The specified Go version 1.23.0 doesn't exist yet (current latest is 1.22). This will cause build failures.

 module github.com/aenix-io/cozystack
 
-go 1.23.0
+go 1.22
📝 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
module github.com/aenix-io/cozystack
go 1.23.0
module github.com/aenix-io/cozystack
go 1.22

@kvaps
Andrei Kvapil (kvaps) force-pushed the cozystack-workload-controller branch from 56850cc to 2d432d2 Compare January 8, 2025 14:42
@kvaps
Andrei Kvapil (kvaps) force-pushed the cozystack-workload-controller branch from a92fdf5 to 6567f96 Compare January 8, 2025 15:25

@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: 3

🔭 Outside diff range comments (2)
packages/system/cozystack-api/templates/deployment.yaml (1)

Line range hint 1-31: Add essential Kubernetes deployment configurations.

The deployment is missing several important configurations for production readiness:

  1. Resource limits and requests
  2. Security context
  3. Liveness and readiness probes
  4. Pod disruption budget for high availability
    spec:
      serviceAccountName: cozystack-api
+      securityContext:
+        runAsNonRoot: true
+        runAsUser: 65534
+        fsGroup: 65534
      containers:
      - name: cozystack-api
        image: "{{ .Values.cozystackAPI.image }}"
+        resources:
+          limits:
+            cpu: 500m
+            memory: 256Mi
+          requests:
+            cpu: 100m
+            memory: 128Mi
+        livenessProbe:
+          httpGet:
+            path: /healthz
+            port: 8080
+          initialDelaySeconds: 15
+          periodSeconds: 20
+        readinessProbe:
+          httpGet:
+            path: /readyz
+            port: 8080
+          initialDelaySeconds: 5
+          periodSeconds: 10
packages/core/platform/bundles/paas-full.yaml (1)

Verify Redis/Sentinel pod labeling implementation

The review comment is valid. While the PR objectives mention Redis and Sentinel pod labeling, no such changes are implemented in the Redis configuration:

  • The RedisFailover deployment only has basic app labels (app.kubernetes.io/instance, app.kubernetes.io/managed-by)
  • No workload.cozystack.io labels are configured
  • The Redis operator CRD supports custom labels through labelWhitelist, but no workload-specific labels are defined

Please implement the required Redis/Sentinel pod labeling changes or clarify if they are handled elsewhere.

🔗 Analysis chain

Line range hint 23-32: Verify complete scope of changes.

While the cozystack-controller implementation is consistent across all bundle files, the PR objectives mention Redis and Sentinel pod labeling which is not visible in these files. Please confirm if additional changes are needed or if the pod labeling is handled elsewhere.

Run this script to check for related changes:

Also applies to: 40-49, 38-47, 65-74

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Look for Redis/Sentinel related changes
# Search for Redis/Sentinel related files and configurations
rg -l 'workload\.cozystack\.io/(kind|type)=(redis|sentinel)'

Length of output: 62


Script:

#!/bin/bash
# Search for Redis/Sentinel related files and configurations using multiple approaches
echo "=== Searching for Redis/Sentinel files ==="
fd -t f -e yaml -e yml . | xargs rg -l -i "redis|sentinel"

echo -e "\n=== Searching for label-related changes in yaml files ==="
fd -t f -e yaml -e yml . | xargs rg -l "labels:|metadata:"

echo -e "\n=== Checking Helm values files for Redis configurations ==="
fd "values*.ya?ml" | xargs rg -l -i "redis"

Length of output: 66891


Script:

#!/bin/bash
# Check Redis configuration files for labeling changes
echo "=== Checking Redis deployment configuration ==="
cat packages/apps/redis/templates/redisfailover.yaml

echo -e "\n=== Checking Redis operator CRD for labeling fields ==="
cat packages/system/redis-operator/charts/redis-operator/crds/databases.spotahome.com_redisfailovers.yaml

Length of output: 67722


Script:

#!/bin/bash
# Search for workload-related configurations in Redis files
echo "=== Checking Redis workload configurations ==="
rg -A 5 -B 5 "workload" packages/apps/redis/
rg -A 5 -B 5 "workload" packages/system/redis-operator/

echo -e "\n=== Checking for Redis values files ==="
cat packages/apps/redis/values.yaml

Length of output: 67888

🧰 Tools
🪛 yamllint (1.35.1)

[warning] 63-63: too few spaces after comma

(commas)


[warning] 69-69: too few spaces after comma

(commas)

♻️ Duplicate comments (6)
internal/telemetry/collector.go (2)

148-155: ⚠️ Potential issue

Fix typos in metric labels bunde_enable and bunde_disable

The metric labels contain typos that could affect metric collection and querying.

-			"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bunde_enable=\"%s\",bunde_disable=\"%s\"} 1\n",
+			"cozy_cluster_info{cozystack_version=\"%s\",kubernetes_version=\"%s\",oidc_enabled=\"%s\",bundle_name=\"%s\",bundle_enable=\"%s\",bundle_disable=\"%s\"} 1\n",

158-172: ⚠️ Potential issue

Fix kernel version reporting in node metrics

The code assumes all nodes have the same kernel version by using nodeList.Items[0].Status.NodeInfo.KernelVersion.

Consider grouping nodes by both OS and kernel version for accurate reporting:

-	nodeOSCount := make(map[string]int)
+	nodeMetrics := make(map[string]map[string]int)
 	for _, node := range nodeList.Items {
 		key := fmt.Sprintf("%s (%s)", node.Status.NodeInfo.OperatingSystem, node.Status.NodeInfo.OSImage)
-		nodeOSCount[key] = nodeOSCount[key] + 1
+		kernel := node.Status.NodeInfo.KernelVersion
+		if _, exists := nodeMetrics[key]; !exists {
+			nodeMetrics[key] = make(map[string]int)
+		}
+		nodeMetrics[key][kernel]++
 	}

-	for osKey, count := range nodeOSCount {
+	for osKey, kernels := range nodeMetrics {
+		for kernel, count := range kernels {
 			metrics.WriteString(fmt.Sprintf(
 				"cozy_nodes_count{os=\"%s\",kernel=\"%s\"} %d\n",
 				osKey,
-				nodeList.Items[0].Status.NodeInfo.KernelVersion,
+				kernel,
 				count,
 			))
+		}
 	}
internal/controller/workloadmonitor_controller.go (2)

94-94: ⚠️ Potential issue

Ensure Workload resource names are unique across the cluster

Using pod.Name as the Workload object's name may lead to conflicts if pods are recreated or if there are naming collisions. Consider incorporating the pod's UID or generating a unique name to ensure the Workload resource names are unique within the cluster.

Apply this diff to modify the workload naming:

-    			Name:      pod.Name, // or any logic to ensure uniqueness
+    			Name:      fmt.Sprintf("%s-%s", pod.Name, pod.UID),

199-232: 🛠️ Refactor suggestion

Optimize Pod to WorkloadMonitor mapping for scalability

In the SetupWithManager method, the mapping function for Pod events lists all WorkloadMonitor resources in the namespace and checks each one for matching selectors. This approach may become a performance bottleneck in namespaces with many WorkloadMonitor objects. Consider using an indexer to map Pods to WorkloadMonitor resources efficiently.

You can set up an index on the WorkloadMonitor selectors and use it to quickly find relevant monitors for a given Pod.

internal/controller/suite_test.go (1)

70-71: ⚠️ Potential issue

Fix incorrect Kubernetes version.

The specified Kubernetes version (1.31.0) is incorrect as it doesn't exist. The latest stable version is 1.28.x.

Apply this diff to fix the version:

-			fmt.Sprintf("1.31.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
+			fmt.Sprintf("1.28.0-%s-%s", runtime.GOOS, runtime.GOARCH)),
go.mod (1)

3-5: ⚠️ Potential issue

Fix invalid Go version.

The specified Go version 1.23.0 doesn't exist yet (current latest is 1.22). This will cause build failures.

Apply this diff to fix the version:

-go 1.23.0
+go 1.22
🧹 Nitpick comments (6)
internal/telemetry/collector.go (1)

32-42: Consider wrapping the discovery client error with more context

The error message could be more descriptive about the operation being performed.

-		return nil, fmt.Errorf("failed to create discovery client: %w", err)
+		return nil, fmt.Errorf("failed to create Kubernetes discovery client for telemetry collection: %w", err)
internal/controller/workloadmonitor_controller.go (1)

61-71: Include resource requests in total resource calculations

Currently, the totalResources map aggregates only the resource limits of the containers. To get a complete picture of resource usage, consider also aggregating the resource requests. This can help in scenarios where requests and limits differ significantly.

Apply this diff to include resource requests in the calculations:

 // Iterate over all containers to aggregate their Limits
 for _, container := range combinedContainers {
     // Aggregate Limits
     for name, qty := range container.Resources.Limits {
         if existing, exists := totalResources[name.String()]; exists {
             existing.Add(qty)
             totalResources[name.String()] = existing
         } else {
             totalResources[name.String()] = qty.DeepCopy()
         }
     }
+    // Aggregate Requests
+    for name, qty := range container.Resources.Requests {
+        if existing, exists := totalResources[name.String()]; exists {
+            existing.Add(qty)
+            totalResources[name.String()] = existing
+        } else {
+            totalResources[name.String()] = qty.DeepCopy()
+        }
+    }
 }
packages/system/cozystack-controller/Makefile (1)

18-20: Ensure robust handling of YAML updates and temporary files

When updating values.yaml with the new image, make sure the script handles any potential errors from the yq command, and ensure that the temporary JSON metadata file is removed even if an error occurs.

Consider adding error checking and using trap to ensure cleanup:

 image-cozystack-controller:
+	set -e
+	trap 'rm -f images/cozystack-controller.json' EXIT
 	docker buildx build -f images/cozystack-controller/Dockerfile ../../.. \
 		--provenance false \
 		--tag $(REGISTRY)/cozystack-controller:$(call settag,$(TAG)) \
 		--cache-from type=registry,ref=$(REGISTRY)/cozystack-controller:latest \
 		--cache-to type=inline \
 		--metadata-file images/cozystack-controller.json \
 		--push=$(PUSH) \
 		--load=$(LOAD)
 	IMAGE="$(REGISTRY)/cozystack-controller:$(call settag,$(TAG))@$$(yq e '."containerimage.digest"' images/cozystack-controller.json -o json -r)" \
 		yq -i '.cozystackController.image = strenv(IMAGE)' values.yaml
-	rm -f images/cozystack-controller.json
cmd/cozystack-controller/main.go (2)

194-196: Improve telemetry collector error handling.

The error handling for the telemetry collector could be improved. Currently, it logs the error at verbosity level 1, which might not be visible in default logging configurations.

Apply this diff to improve error visibility:

-		setupLog.V(1).Error(err, "unable to create telemetry collector, telemetry will be disabled")
+		setupLog.Error(err, "unable to create telemetry collector, telemetry will be disabled")

200-201: Remove redundant error logging.

The error is logged twice with different verbosity levels, which is redundant.

Apply this diff to remove the redundant log:

 			setupLog.Error(err, "unable to set up telemetry collector")
-			setupLog.V(1).Error(err, "unable to set up telemetry collector, continuing without telemetry")
packages/core/platform/bundles/paas-full.yaml (1)

69-69: Fix comma spacing in dependencies.

Add a space after the comma in dependencies for consistency with the codebase style:

-  dependsOn: [cilium,kubeovn]
+  dependsOn: [cilium, kubeovn]
🧰 Tools
🪛 yamllint (1.35.1)

[warning] 69-69: too few spaces after comma

(commas)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb264e1 and 6567f96.

⛔ Files ignored due to path filters (5)
  • go.sum is excluded by !**/*.sum
  • pkg/generated/applyconfiguration/apps/v1alpha1/application.go is excluded by !**/generated/**
  • pkg/generated/applyconfiguration/utils.go is excluded by !**/generated/**
  • pkg/generated/listers/apps/v1alpha1/application.go is excluded by !**/generated/**
  • pkg/generated/openapi/zz_generated.openapi.go is excluded by !**/generated/**
📒 Files selected for processing (53)
  • Makefile (1 hunks)
  • api/api-rules/cozystack_api_violation_exceptions.list (1 hunks)
  • api/v1alpha1/groupversion_info.go (1 hunks)
  • api/v1alpha1/workload_types.go (1 hunks)
  • api/v1alpha1/workloadmonitor_types.go (1 hunks)
  • api/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • cmd/cozystack-api/main.go (1 hunks)
  • cmd/cozystack-controller/main.go (1 hunks)
  • go.mod (3 hunks)
  • hack/boilerplate.go.txt (1 hunks)
  • hack/update-codegen.sh (2 hunks)
  • internal/controller/suite_test.go (1 hunks)
  • internal/controller/workloadmonitor_controller.go (1 hunks)
  • internal/telemetry/collector.go (1 hunks)
  • internal/telemetry/config.go (1 hunks)
  • packages/core/platform/bundles/distro-full.yaml (1 hunks)
  • packages/core/platform/bundles/distro-hosted.yaml (1 hunks)
  • packages/core/platform/bundles/paas-full.yaml (1 hunks)
  • packages/core/platform/bundles/paas-hosted.yaml (1 hunks)
  • packages/system/cozystack-api/images/cozystack-api/Dockerfile (2 hunks)
  • packages/system/cozystack-api/templates/deployment.yaml (1 hunks)
  • packages/system/cozystack-controller/.devcontainer/devcontainer.json (1 hunks)
  • packages/system/cozystack-controller/.devcontainer/post-install.sh (1 hunks)
  • packages/system/cozystack-controller/.dockerignore (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/lint.yml (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/test-e2e.yml (1 hunks)
  • packages/system/cozystack-controller/.github/workflows/test.yml (1 hunks)
  • packages/system/cozystack-controller/.gitignore (1 hunks)
  • packages/system/cozystack-controller/.golangci.yml (1 hunks)
  • packages/system/cozystack-controller/Chart.yaml (1 hunks)
  • packages/system/cozystack-controller/Makefile (1 hunks)
  • packages/system/cozystack-controller/images/cozystack-controller/Dockerfile (1 hunks)
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloadmonitors.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloads.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/deployment.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/rbac-bind.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/rbac.yaml (1 hunks)
  • packages/system/cozystack-controller/templates/sa.yaml (1 hunks)
  • packages/system/cozystack-controller/values.yaml (1 hunks)
  • pkg/apis/apps/fuzzer/fuzzer.go (1 hunks)
  • pkg/apis/apps/install/install.go (1 hunks)
  • pkg/apis/apps/install/roundtrip_test.go (1 hunks)
  • pkg/apis/apps/v1alpha1/doc.go (1 hunks)
  • pkg/apis/apps/v1alpha1/register.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.conversion.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go (1 hunks)
  • pkg/apis/apps/v1alpha1/zz_generated.defaults.go (1 hunks)
  • pkg/apis/apps/validation/validation.go (1 hunks)
  • pkg/apiserver/apiserver.go (1 hunks)
  • pkg/apiserver/scheme_test.go (1 hunks)
  • pkg/cmd/server/start.go (1 hunks)
  • pkg/registry/apps/application/rest.go (1 hunks)
  • pkg/registry/registry.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (37)
  • pkg/apis/apps/v1alpha1/zz_generated.conversion.go
  • hack/boilerplate.go.txt
  • packages/system/cozystack-controller/templates/sa.yaml
  • Makefile
  • pkg/apis/apps/validation/validation.go
  • packages/system/cozystack-controller/.dockerignore
  • pkg/apis/apps/v1alpha1/zz_generated.deepcopy.go
  • pkg/apis/apps/v1alpha1/zz_generated.defaults.go
  • api/api-rules/cozystack_api_violation_exceptions.list
  • packages/system/cozystack-controller/Chart.yaml
  • pkg/cmd/server/start.go
  • pkg/registry/registry.go
  • pkg/apis/apps/install/roundtrip_test.go
  • cmd/cozystack-api/main.go
  • pkg/apis/apps/fuzzer/fuzzer.go
  • packages/system/cozystack-controller/templates/rbac-bind.yaml
  • packages/system/cozystack-controller/.devcontainer/devcontainer.json
  • packages/system/cozystack-controller/.gitignore
  • pkg/apis/apps/v1alpha1/register.go
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloads.yaml
  • packages/system/cozystack-api/images/cozystack-api/Dockerfile
  • packages/system/cozystack-controller/templates/rbac.yaml
  • packages/system/cozystack-controller/.github/workflows/test.yml
  • internal/telemetry/config.go
  • packages/system/cozystack-controller/.github/workflows/lint.yml
  • pkg/registry/apps/application/rest.go
  • pkg/apis/apps/v1alpha1/doc.go
  • packages/system/cozystack-controller/images/cozystack-controller/Dockerfile
  • packages/system/cozystack-controller/.golangci.yml
  • pkg/apiserver/apiserver.go
  • packages/system/cozystack-controller/.github/workflows/test-e2e.yml
  • packages/system/cozystack-controller/templates/crds/cozystack.io_workloadmonitors.yaml
  • pkg/apis/apps/install/install.go
  • packages/system/cozystack-controller/.devcontainer/post-install.sh
  • api/v1alpha1/workloadmonitor_types.go
  • api/v1alpha1/workload_types.go
  • api/v1alpha1/zz_generated.deepcopy.go
🧰 Additional context used
🪛 yamllint (1.35.1)
packages/core/platform/bundles/paas-full.yaml

[warning] 69-69: too few spaces after comma

(commas)

packages/system/cozystack-controller/templates/deployment.yaml

[error] 25-25: syntax error: could not find expected ':'

(syntax)

🪛 golangci-lint (1.62.2)
pkg/apiserver/scheme_test.go

22-22: could not import github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer (-: # github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer
pkg/apis/apps/fuzzer/fuzzer.go:29:16: undefined: apps.ApplicationSpec)

(typecheck)

🔇 Additional comments (16)
pkg/apiserver/scheme_test.go (1)

22-22: Verify the import path update and fix build failure

While the import path update from aenix.io to aenix-io is syntactically correct, the static analysis indicates that apps.ApplicationSpec is undefined in the fuzzer package. This needs to be addressed to ensure the tests can run successfully.

Run this script to verify the package structure:

#!/bin/bash
# Check if the package exists and is properly structured
fd -t f -e go . | xargs grep -l "type ApplicationSpec struct"

# Verify the import path is consistently updated across the codebase
rg "github.com/aenix.io/cozystack" -l
🧰 Tools
🪛 golangci-lint (1.62.2)

22-22: could not import github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer (-: # github.com/aenix-io/cozystack/pkg/apis/apps/fuzzer
pkg/apis/apps/fuzzer/fuzzer.go:29:16: undefined: apps.ApplicationSpec)

(typecheck)

internal/telemetry/collector.go (1)

79-108: LGTM! Well-structured size grouping logic

The exponential grouping of PV sizes is well-implemented with clear boundaries and comprehensive coverage.

packages/system/cozystack-api/templates/deployment.yaml (1)

9-9: Verify horizontal scaling prerequisites.

While increasing replicas improves availability, please ensure:

  1. The application is stateless or handles state properly
  2. Load balancing is configured correctly
  3. Database connections are properly managed across replicas
✅ Verification successful

Scaling to 2 replicas appears safe

The deployment is properly configured for horizontal scaling:

  • Uses ConfigMap for configuration (no shared state)
  • Has proper service configuration for load balancing
  • No persistent volume claims that could cause conflicts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if PVC is used (which might indicate stateful data)
rg -l 'kind:\s+PersistentVolumeClaim' packages/system/cozystack-api/
# Check if any pod affinity/anti-affinity rules exist
rg -l 'podAntiAffinity|podAffinity' packages/system/cozystack-api/

Length of output: 139


Script:

#!/bin/bash
# Check for volume mounts and storage configurations
rg -g 'deployment.yaml' 'volume[Mm]ounts?:|volumes:' packages/system/cozystack-api/

# Check for service configuration
cat packages/system/cozystack-api/templates/service.yaml 2>/dev/null || echo "No service.yaml found"

# Look for database connection configurations
rg -g '*.yaml' -i '(DATABASE|DB_|MYSQL|POSTGRES)' packages/system/cozystack-api/

# Check for session configurations
rg -g '*.yaml' -i '(SESSION|REDIS|CACHE)' packages/system/cozystack-api/

Length of output: 2224


Script:

#!/bin/bash
# Check volume configuration details
rg -A 10 'volumeMounts:|volumes:' packages/system/cozystack-api/templates/deployment.yaml

# Check for any shared storage claims
rg 'claimName:|storageClassName:' packages/system/cozystack-api/templates/deployment.yaml

Length of output: 475

packages/system/cozystack-controller/templates/deployment.yaml (2)

24-28: Remove debug logging in production.

Debug logging should not be enabled in production as it can impact performance and potentially leak sensitive information.

        {{- if .Values.cozystackController.debug }}
-        - --zap-log-level=debug
        {{- else }}
        - --zap-log-level=info
        {{- end }}

Consider using environment-specific values files to manage logging levels instead of conditional templating.

🧰 Tools
🪛 yamllint (1.35.1)

[error] 25-25: syntax error: could not find expected ':'

(syntax)


1-31: Add essential Kubernetes deployment configurations.

The deployment is missing several important configurations for production readiness:

  1. Resource limits and requests
  2. Security context
  3. Liveness and readiness probes
  4. Pod disruption budget for high availability
    spec:
      serviceAccountName: cozystack-controller
+      securityContext:
+        runAsNonRoot: true
+        runAsUser: 65534
+        fsGroup: 65534
      containers:
      - name: cozystack-controller
        image: "{{ .Values.cozystackController.image }}"
+        resources:
+          limits:
+            cpu: 500m
+            memory: 256Mi
+          requests:
+            cpu: 100m
+            memory: 128Mi
+        livenessProbe:
+          httpGet:
+            path: /healthz
+            port: 8081
+          initialDelaySeconds: 15
+          periodSeconds: 20
+        readinessProbe:
+          httpGet:
+            path: /readyz
+            port: 8081
+          initialDelaySeconds: 5
+          periodSeconds: 10
🧰 Tools
🪛 yamllint (1.35.1)

[error] 25-25: syntax error: could not find expected ':'

(syntax)

packages/system/cozystack-controller/values.yaml (1)

2-5: Verify image tag and digest consistency

The image specified includes both a tag (latest) and a digest (sha256:...). Ensure that the tag and digest correspond to the same image version to avoid potential inconsistencies during deployment.

Run the following script to check if the tag and digest point to the same image:

api/v1alpha1/groupversion_info.go (3)

17-20: LGTM! API group configuration looks good.

The API group configuration is well-structured with appropriate kubebuilder markers and group name.


27-36: LGTM! Group version and scheme configuration looks good.

The group version and scheme configuration is correctly implemented with proper variable declarations and initialization.


1-2: ⚠️ Potential issue

Fix incorrect copyright year.

The copyright year is set to 2025, which is in the future. Update it to the current year.

Apply this diff to fix the copyright year:

-Copyright 2025.
+Copyright 2024.

Likely invalid or redundant comment.

hack/update-codegen.sh (2)

25-25: LGTM! Controller-gen configuration looks good.

The controller-gen tool is correctly configured with a specific version for reproducible builds.


51-52: LGTM! Code generation commands look good.

The commands for generating object headers, RBAC, and CRDs are correctly implemented with appropriate paths and options.

cmd/cozystack-controller/main.go (1)

145-148: Consider configuring custom TLS certificates for production environments.

The metrics server currently relies on automatically generated self-signed certificates when CertDir, CertName, and KeyName are not specified. While this setup is convenient for development and testing, it's not recommended for production due to security concerns.

packages/core/platform/bundles/distro-hosted.yaml (1)

23-32: LGTM! Verify telemetry configuration.

The release entry is well-structured with appropriate dependencies. The telemetry configuration is properly guarded by the condition.

Run this script to verify the telemetry configuration:

✅ Verification successful

Telemetry configuration is consistent and correctly implemented

The telemetry configuration is consistently implemented across all bundle files and properly integrated with the cozystack-controller deployment.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify telemetry configuration consistency across bundle files
# Check if telemetry configuration exists in cozystack ConfigMap
rg -A 1 'telemetry-enabled:' 'cozy-system/cozystack'

Length of output: 112


Script:

#!/bin/bash
# Search for telemetry configuration in all YAML files
echo "=== Searching for telemetry configuration in YAML files ==="
rg -t yaml "telemetry-enabled" 

echo -e "\n=== Looking for ConfigMap definitions with telemetry ==="
ast-grep --pattern 'kind: ConfigMap'

echo -e "\n=== Searching for other telemetry-related settings ==="
rg "telemetry" -t yaml

Length of output: 14115

packages/core/platform/bundles/distro-full.yaml (1)

40-49: LGTM! Implementation is consistent.

The release entry maintains consistency with other bundle files in terms of placement, dependencies, and telemetry configuration.

packages/core/platform/bundles/paas-hosted.yaml (1)

38-47: Verify empty dependencies list.

While the release entry is consistent with other bundle files, it has no dependencies specified. Please confirm if this is intentional for the hosted environment, as other bundle files depend on cilium.

packages/core/platform/bundles/paas-full.yaml (1)

65-74: LGTM! Implementation is consistent with extended dependencies.

The release entry properly includes both cilium and kubeovn dependencies, matching the pattern of other releases in this full deployment configuration.

🧰 Tools
🪛 yamllint (1.35.1)

[warning] 69-69: too few spaces after comma

(commas)

Comment on lines +44 to +66
// Start implements manager.Runnable
func (c *Collector) Start(ctx context.Context) error {
if c.config.Disabled {
return nil
}

c.ticker = time.NewTicker(c.config.Interval)
c.stopCh = make(chan struct{})

// Initial collection
c.collect(ctx)

for {
select {
case <-ctx.Done():
c.ticker.Stop()
close(c.stopCh)
return nil
case <-c.ticker.C:
c.collect(ctx)
}
}
}

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.

🛠️ Refactor suggestion

Add mutex protection for ticker and stopCh

The ticker and stopCh fields could be accessed concurrently by Start and Stop methods. Consider adding mutex protection.

 type Collector struct {
 	client          client.Client
 	discoveryClient discovery.DiscoveryInterface
 	config          *Config
+	mu             sync.Mutex
 	ticker         *time.Ticker
 	stopCh         chan struct{}
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +271 to +292
// sendMetrics sends collected metrics to the configured endpoint
func (c *Collector) sendMetrics(clusterID, metrics string) error {
req, err := http.NewRequest("POST", c.config.Endpoint, bytes.NewBufferString(metrics))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}

req.Header.Set("Content-Type", "text/plain")
req.Header.Set("X-Cluster-ID", clusterID)

resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

return nil
}

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.

🛠️ Refactor suggestion

Improve HTTP client handling

The current implementation has two potential issues:

  1. No timeout set for HTTP requests
  2. Response body not fully read before closing
+	client := &http.Client{
+		Timeout: 10 * time.Second,
+	}
+
 	req, err := http.NewRequest("POST", c.config.Endpoint, bytes.NewBufferString(metrics))
 	if err != nil {
 		return fmt.Errorf("failed to create request: %w", err)
 	}

 	req.Header.Set("Content-Type", "text/plain")
 	req.Header.Set("X-Cluster-ID", clusterID)

-	resp, err := http.DefaultClient.Do(req)
+	resp, err := client.Do(req)
 	if err != nil {
 		return fmt.Errorf("failed to send request: %w", err)
 	}
-	defer resp.Body.Close()
+	defer func() {
+		// Drain the body before closing
+		_, _ = io.Copy(io.Discard, resp.Body)
+		resp.Body.Close()
+	}()

Also, consider adding the following import:

+	"io"
📝 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
// sendMetrics sends collected metrics to the configured endpoint
func (c *Collector) sendMetrics(clusterID, metrics string) error {
req, err := http.NewRequest("POST", c.config.Endpoint, bytes.NewBufferString(metrics))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "text/plain")
req.Header.Set("X-Cluster-ID", clusterID)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
return nil
}
// sendMetrics sends collected metrics to the configured endpoint
func (c *Collector) sendMetrics(clusterID, metrics string) error {
client := &http.Client{
Timeout: 10 * time.Second,
}
req, err := http.NewRequest("POST", c.config.Endpoint, bytes.NewBufferString(metrics))
if err != nil {
return fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "text/plain")
req.Header.Set("X-Cluster-ID", clusterID)
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %w", err)
}
defer func() {
// Drain the body before closing
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
}()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}
return nil
}

labels:
app: cozystack-controller
spec:
replicas: 1

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.

🛠️ Refactor suggestion

Consider high availability for the controller.

Running a single replica of the controller could create a single point of failure. Consider:

  1. Increasing replicas for high availability
  2. Adding topology spread constraints for better distribution
  spec:
-  replicas: 1
+  replicas: 2
+  topologySpreadConstraints:
+  - maxSkew: 1
+    topologyKey: kubernetes.io/hostname
+    whenUnsatisfiable: DoNotSchedule
+    labelSelector:
+      matchLabels:
+        app: cozystack-controller
📝 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
replicas: 1
spec:
replicas: 2
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: cozystack-controller

@kvaps
Andrei Kvapil (kvaps) force-pushed the cozystack-workload-controller branch from 1f76592 to 946fd6e Compare January 8, 2025 16:31

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.

may be better precommit?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I forgot to remove that, thanks

// Parse telemetry interval
interval, err := time.ParseDuration(telemetryInterval)
if err != nil {
setupLog.Error(err, "invalid telemetry interval")

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.

why not

log.Fatalf("Invalid telemetry interval: %v", err)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

type logr.Logger has no field or method Fatalf

@kvaps
Andrei Kvapil (kvaps) merged commit 227848a into main Jan 9, 2025
@kvaps
Andrei Kvapil (kvaps) deleted the cozystack-workload-controller branch January 9, 2025 11:24
@coderabbitai coderabbitai Bot mentioned this pull request Jan 16, 2025
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 size/XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants