{"id":48801141,"url":"https://github.com/decocms/operator","last_synced_at":"2026-05-07T18:08:50.731Z","repository":{"id":324085522,"uuid":"1095081115","full_name":"decocms/operator","owner":"decocms","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-04T13:36:04.000Z","size":261,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-04T14:36:34.253Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/decocms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-12T15:08:07.000Z","updated_at":"2026-04-24T03:27:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/decocms/operator","commit_stats":null,"previous_names":["decocms/operator"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/decocms/operator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Foperator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Foperator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Foperator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Foperator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/decocms","download_url":"https://codeload.github.com/decocms/operator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Foperator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32749686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-07T02:14:30.463Z","status":"ssl_error","status_checked_at":"2026-05-07T02:14:29.405Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-14T03:00:42.017Z","updated_at":"2026-05-07T18:08:50.687Z","avatar_url":"https://github.com/decocms.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Deco CMS Operator\n\nA Kubernetes operator for Deco CMS that manages configuration resources and automatically injects them into Knative Services.\n\n## Description\n\nThe Deco CMS operator manages **Decofile** custom resources, which represent configuration files for your Deco applications. The operator enables you to:\n- Define JSON configuration data as Kubernetes custom resources (Decofiles)\n- Automatically create ConfigMaps from Decofile resources\n- Inject ConfigMaps into Knative Services via annotations using a mutating webhook\n\n## Features\n\n### Decofile Management\n- ✅ **Dual Source Support**: Inline JSON or GitHub repository sources\n- ✅ **Automated ConfigMap Generation**: Creates/updates ConfigMaps from Decofile resources\n- ✅ **Unified Format**: All sources produce consistent `decofile.json` format\n- ✅ **Special Filename Support**: Preserves filenames with `%`, spaces, and special characters\n- ✅ **Owner References**: Automatic cleanup when Decofiles are deleted\n\n### Knative Integration\n- ✅ **Webhook-based Injection**: Automatically injects ConfigMaps into Knative Services\n- ✅ **File Mounting**: Mounts as `/app/decofile/decofile.json` by default\n- ✅ **DECO_RELEASE Env Var**: Auto-injected for application discovery\n- ✅ **Custom Mount Paths**: Configurable via annotations\n- ✅ **Label-Based Tracking**: Pods labeled for easy discovery\n\n### Change Notifications\n- ✅ **Automatic Reload**: Notifies pods when ConfigMaps change\n- ✅ **Smart Delay**: 60-second wait for kubelet sync\n- ✅ **Retry Logic**: Exponential backoff with 5 attempts\n- ✅ **Direct Pod Communication**: HTTP calls to reload endpoints\n- ✅ **Token Authentication**: UUID tokens for secure reload requests\n\n### Production Ready\n- ✅ **Multi-Instance Ready**: Built-in leader election for high availability\n- ✅ **Helm Support**: Install with Helm for easy configuration\n- ✅ **CI/CD Pipeline**: Automated builds and validation\n- ✅ **Complete Testing**: Unit, integration, and e2e tests\n\n## Quick Start\n\n### Installation with Helm\n\n**From GitHub Release (Recommended)**:\n\n```bash\n# Install from release\nhelm install deco \\\n  https://github.com/decocms/operator/releases/download/v0.1.0/deco-operator-0.1.0.tgz \\\n  --namespace operator-system \\\n  --create-namespace \\\n  --wait\n\n# With GitHub token for private repos\nhelm install deco \\\n  https://github.com/decocms/operator/releases/download/v0.1.0/deco-operator-0.1.0.tgz \\\n  --namespace operator-system \\\n  --create-namespace \\\n  --set github.token=ghp_your_token \\\n  --wait\n```\n\n**From Source**:\n\n```bash\n# Clone the repository\ngit clone https://github.com/decocms/operator.git\ncd operator\n\n# Install with Helm\nhelm install deco chart/ \\\n  --namespace operator-system \\\n  --create-namespace \\\n  --wait\n```\n\n### Verify Installation\n\n```bash\n# Check operator is running\nkubectl get pods -n operator-system\n\n# Check CRD is installed\nkubectl get crd decofiles.deco.sites\n\n# View operator logs\nkubectl logs -n operator-system -l control-plane=controller-manager -f\n```\n\n### Prerequisites\n\n- Kubernetes cluster (1.16+)\n- Helm 3.x (for installation)\n- cert-manager (for webhook TLS)\n- Knative Serving (for injection features)\n\nSee [DEPLOYMENT.md](DEPLOYMENT.md) for detailed deployment options, [HELM.md](HELM.md) for complete Helm documentation, and [docs/RELOAD_AUTHENTICATION.md](docs/RELOAD_AUTHENTICATION.md) for securing reload endpoints.\n\n## Usage\n\n### Creating a Decofile\n\nThe Decofile operator supports two source types for configuration data:\n\n#### 1. Inline Source\n\nDefine JSON configuration directly in the Decofile spec:\n\n```yaml\napiVersion: deco.sites/v1alpha1\nkind: Decofile\nmetadata:\n  name: decofile-miess-01-main\n  namespace: sites-miess-01\nspec:\n  source: inline\n  inline:\n    value:\n      config.json:\n        key: \"value\"\n        environment: \"production\"\n      data.json:\n        foo: \"bar\"\n```\n\n#### 2. GitHub Source\n\nFetch configuration from a GitHub repository:\n\n```yaml\napiVersion: deco.sites/v1alpha1\nkind: Decofile\nmetadata:\n  name: decofile-mysite-main\n  namespace: sites-mysite\nspec:\n  source: github\n  github:\n    org: deco-sites\n    repo: mysite\n    commit: main  # or specific commit SHA\n    path: .deco/blocks\n    secret: github-token\n```\n\n**GitHub Secret Setup:**\n\nCreate a secret with your GitHub personal access token:\n\n```yaml\napiVersion: v1\nkind: Secret\nmetadata:\n  name: github-token\n  namespace: sites-mysite\ntype: Opaque\nstringData:\n  token: ghp_your_github_personal_access_token_here\n```\n\nApply it:\n\n```bash\n# For inline source\nkubectl apply -f config/samples/deco.sites_v1alpha1_decofile.yaml\n\n# For GitHub source\nkubectl apply -f config/samples/github_secret.yaml\nkubectl apply -f config/samples/deco.sites_v1alpha1_decofile_github.yaml\n```\n\nThe operator will automatically create a ConfigMap named `decofile-\u003cname\u003e` with the data.\n\n### Injecting into Knative Services\n\nAdd annotations to your Knative Service to automatically inject the Decofile:\n\n```yaml\napiVersion: serving.knative.dev/v1\nkind: Service\nmetadata:\n  name: my-site\n  namespace: sites-mysite  # Namespace must start with \"sites-\" for \"default\" resolution\n  annotations:\n    deco.sites/decofile-inject: \"default\"  # Resolves to \"decofile-mysite-main\"\n    # deco.sites/decofile-mount-path: \"/custom/path\"  # Optional: custom mount directory\nspec:\n  template:\n    spec:\n      containers:\n        - name: app\n          image: your-deco-app:latest\n```\n\n**What the webhook does automatically:**\n1. ✅ Resolves the Decofile name (e.g., `\"default\"` → `decofile-mysite-main`)\n2. ✅ Fetches the ConfigMap from the Decofile status\n3. ✅ Mounts ConfigMap as `/app/decofile/decofile.json` (or custom path)\n4. ✅ Injects `DECO_RELEASE=file:///app/decofile/decofile.json` environment variable\n5. ✅ Labels pod with `deco.sites/decofile: \u003cname\u003e` for tracking\n\n**Your application receives:**\n- `DECO_RELEASE` env var pointing to the config file\n- Single JSON file with all configuration: `{\"file1.json\": {...}, \"file2.json\": {...}}`\n- Auto-updates when Decofile changes (with 60s kubelet sync delay)\n\n## Annotations\n\n### `deco.sites/decofile-inject`\n\nSpecifies which Decofile to inject into the Service.\n\n- **Value: `\"default\"`** - Resolves to `decofile-{site}-main` where `{site}` is extracted from the namespace by stripping the `sites-` prefix\n  - Example: namespace `sites-miess-01` → site `miess-01` → decofile `decofile-miess-01-main`\n- **Value: `\"\u003cname\u003e\"`** - Uses the specified Decofile name directly\n\n**Required:** Namespace must start with `sites-` when using `\"default\"`\n\n### `deco.sites/decofile-mount-path`\n\nOptional annotation to customize the mount path for the ConfigMap.\n\n- **Default:** `/app/deco/.deco/blocks`\n- **Example:** `/custom/config/path`\n\n## Source Types\n\n### Inline Source\n\nBest for:\n- Small configuration files\n- Quick testing and development\n- Static configurations\n\n**Pros:**\n- Simple and straightforward\n- No external dependencies\n- Immediate updates\n\n**Cons:**\n- Configuration stored in Kubernetes\n- Harder to version control\n- Manual updates required\n\n### GitHub Source\n\nBest for:\n- GitOps workflows\n- Versioned configurations\n- Shared configurations across teams\n- Large configuration files\n\n**Pros:**\n- Version control via Git\n- Audit trail in Git history\n- Easy rollbacks (change commit SHA)\n- Centralized configuration management\n- Supports private repositories\n\n**Cons:**\n- Requires GitHub access token\n- Network dependency\n- Slightly more complex setup\n\n**How it works:**\n\n1. Controller fetches GitHub credentials from Kubernetes secret\n2. Downloads repository ZIP from `https://codeload.github.com/{org}/{repo}/zip/{commit}`\n3. Extracts files from specified path\n4. Creates ConfigMap with file contents\n\n**Security:**\n- Tokens stored in Kubernetes secrets\n- Use read-only tokens (minimum required permissions)\n- Supports private repositories\n\n## Architecture\n\nThe Deco CMS Operator consists of three main components:\n\n### 1. Decofile Controller\n\nManages the lifecycle of Decofile custom resources:\n\n**Responsibilities:**\n- Watches Decofile resources for changes\n- Retrieves configuration from inline or GitHub sources  \n- Creates/updates ConfigMaps with unified `decofile.json` format\n- Detects ConfigMap changes and notifies affected pods\n- Updates status with conditions and metadata\n\n**Source Implementations:**\n- `InlineSource` - Parses inline JSON values\n- `GitHubSource` - Downloads from GitHub repositories\n- Strategy pattern for easy extensibility\n\n**Change Notifications:**\n- Discovers pods via `deco.sites/decofile` label\n- Calls `/.decofile/reload` on each pod with token authentication\n- Sends `Authorization: Token \u003cuuid\u003e` header for security\n- Waits for pods to confirm reload before completing reconciliation\n\n### 2. Mutating Webhook\n\nIntercepts Knative Service CREATE/UPDATE operations:\n\n**Injection Process:**\n1. Checks for `deco.sites/decofile-inject` annotation\n2. Resolves Decofile name (\"default\" or explicit)\n3. Fetches ConfigMap name from Decofile status\n4. Mounts ConfigMap as `/app/decofile/` directory\n5. Injects `DECO_RELEASE` environment variable\n6. Labels pods with `deco.sites/decofile` for tracking\n\n**Features:**\n- Supports custom mount paths via annotation\n- Handles \"default\" resolution from namespace\n- TLS secured via cert-manager\n\n### 3. Pod Notifier\n\nNotifies pods about configuration changes:\n\n**Flow:**\n- Triggered when ConfigMap data changes\n- Queries pods by Decofile label\n- HTTP GET with `?delay=60000` parameter\n- Pods wait for kubelet sync before reading file\n- Retries with exponential backoff\n\n### High Availability\n\n- ✅ **Leader Election**: Only one controller instance reconciles\n- ✅ **Stateless Webhooks**: All instances handle requests\n- ✅ **Horizontal Scaling**: Configure via `replicaCount` in Helm\n- ✅ **Automatic Failover**: Built into controller-runtime\n\n## Development\n\n### Prerequisites\n\n- Go 1.21+\n- Docker\n- kubectl\n- operator-sdk\n\n### Running Locally\n\n1. Install the CRDs:\n\n```bash\nmake install\n```\n\n2. Run the controller:\n\n```bash\nmake run\n```\n\n### Testing\n\n```bash\n# Run unit tests\nmake test\n\n# Run with coverage\nmake test-coverage\n```\n\n### Building\n\n```bash\n# Build binary\nmake build\n\n# Build Docker image\nmake docker-build IMG=\u003cyour-registry\u003e/decofile-operator:tag\n\n# Push Docker image\nmake docker-push IMG=\u003cyour-registry\u003e/decofile-operator:tag\n```\n\n## Configuration\n\n### RBAC Permissions\n\nThe operator requires:\n- Full access to Decofiles (our CRD)\n- Full access to ConfigMaps\n- Read access to Knative Services (for webhook)\n\n### Webhook Configuration\n\nThe webhook is automatically configured with:\n- TLS certificates via cert-manager\n- Mutating webhook for Knative Services\n- Validating webhook (optional, currently disabled)\n\n## Troubleshooting\n\n### Webhook Not Working\n\n1. Check cert-manager is installed and running\n2. Verify the webhook configuration:\n\n```bash\nkubectl get mutatingwebhookconfiguration\nkubectl get certificate -n decofile-operator-system\n```\n\n3. Check webhook logs:\n\n```bash\nkubectl logs -n decofile-operator-system deployment/decofile-operator-controller-manager\n```\n\n### ConfigMap Not Created\n\n1. Check the Decofile resource:\n\n```bash\nkubectl get decofile -n \u003cnamespace\u003e \u003cname\u003e -o yaml\n```\n\n2. Check controller logs:\n\n```bash\nkubectl logs -n decofile-operator-system deployment/decofile-operator-controller-manager\n```\n\n### Decofile Not Creating ConfigMap\n\n**For inline source:**\n- Check the YAML syntax is valid\n- Ensure `source: inline` is set\n- Verify `inline.value` contains valid JSON\n\n**For GitHub source:**\n- Verify the secret exists and contains valid token\n- Check GitHub credentials: `kubectl get secret github-token -n \u003cnamespace\u003e -o yaml`\n- Ensure org, repo, commit, and path are correct\n- Check if repository is private (requires valid token)\n- Verify network connectivity from cluster to GitHub\n\n### Webhook Denying Service Creation\n\nCommon errors:\n- **\"Decofile X not found\"**: Ensure the Decofile exists in the same namespace\n- **\"namespace does not start with 'sites-'\"**: When using \"default\", the namespace must start with `sites-` prefix\n- **\"does not have a ConfigMap created yet\"**: Wait for controller to reconcile the Decofile\n- **\"failed to get Decofile\"**: Check the Decofile name and namespace\n\n### GitHub Download Failures\n\nCommon errors:\n- **\"failed to download: status 404\"**: Repository not found or token lacks access\n- **\"failed to get secret\"**: Secret doesn't exist in the namespace\n- **\"secret does not contain 'token' key\"**: Secret must have a `token` field\n- **\"failed to read zip\"**: Invalid ZIP file or network issue\n\n**Debugging:**\n```bash\n# Check controller logs\nkubectl logs -n decofile-operator-system deployment/decofile-operator-controller-manager\n\n# Check Decofile status\nkubectl get decofile \u003cname\u003e -n \u003cnamespace\u003e -o yaml\n\n# Verify secret\nkubectl get secret github-token -n \u003cnamespace\u003e -o jsonpath='{.data.token}' | base64 -d\n\n# Test GitHub access manually\ncurl -H \"Authorization: token YOUR_TOKEN\" https://codeload.github.com/org/repo/zip/main\n```\n\n## Uninstall\n\nTo uninstall the operator:\n\n```bash\nmake undeploy\n```\n\nThis will remove:\n- The operator deployment\n- Webhook configurations\n- RBAC resources\n- CRDs (and all Decofile resources)\n\n## Contributing\n\nContributions are welcome! Please:\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests\n5. Submit a pull request\n\n## License\n\nCopyright 2025.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Foperator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdecocms%2Foperator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Foperator/lists"}