{"id":18810360,"url":"https://github.com/absaoss/go-k8s-operator-binder","last_synced_at":"2026-05-04T14:43:48.506Z","repository":{"id":65898147,"uuid":"601645276","full_name":"AbsaOSS/go-k8s-operator-binder","owner":"AbsaOSS","description":"Binds Environment variables and Kubernetes maps (such as annotations and labels) to GO structures","archived":false,"fork":false,"pushed_at":"2023-02-14T16:25:07.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-12-29T23:25:44.512Z","etag":null,"topics":["configuration","go","golang","k8s","kubernetes","library","open-source","operator","operator-framework"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AbsaOSS.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-14T14:11:24.000Z","updated_at":"2023-02-14T14:17:43.000Z","dependencies_parsed_at":"2023-03-02T18:30:33.898Z","dependency_job_id":null,"html_url":"https://github.com/AbsaOSS/go-k8s-operator-binder","commit_stats":{"total_commits":4,"total_committers":1,"mean_commits":4.0,"dds":0.0,"last_synced_commit":"e3e21ff8797e6ac1877c4d7081e742d0ff25f285"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Fgo-k8s-operator-binder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Fgo-k8s-operator-binder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Fgo-k8s-operator-binder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbsaOSS%2Fgo-k8s-operator-binder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AbsaOSS","download_url":"https://codeload.github.com/AbsaOSS/go-k8s-operator-binder/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239744074,"owners_count":19689599,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["configuration","go","golang","k8s","kubernetes","library","open-source","operator","operator-framework"],"created_at":"2024-11-07T23:19:57.410Z","updated_at":"2026-01-10T17:30:14.041Z","avatar_url":"https://github.com/AbsaOSS.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# k8s-go-map-binder\n[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)\n[![Go Reference](https://pkg.go.dev/badge/github.com/AbsaOSS/go-k8s-operator-binder.svg)](https://pkg.go.dev/github.com/AbsaOSS/go-k8s-operator-binder?branch=main)\n![Build Status](https://github.com/AbsaOSS/go-k8s-operator-binder/actions/workflows/test.yaml/badge.svg?branch=main)\n![Linter](https://github.com/AbsaOSS/go-k8s-operator-binder/actions/workflows/lint.yaml/badge.svg?branch=main)\n[![Go Report Card](https://goreportcard.com/badge/github.com/AbsaOSS/go-k8s-operator-binder)](https://goreportcard.com/report/github.com/AbsaOSS/go-k8s-operator-binder?branch=main)\n\nMy Kubernetes operators usually read configurations from two sources. The first is Config values that sit in \nEnvironment Variables. The second configuration is obtained at runtime by reading annotations and labels.\n\nThis library can bind these configurations to GO structures in a uniform way. Besides the actual parsing,\nit also offers ways to bind fields such as default values, require, value protection, private fields and \nnested structures.\n\n## Table of Content\n- [QuickStart](#quickstart)\n  - [K8s binder](#k8s-binder)\n  - [Environment variables binder](#environment-variables-binder)\n- [Supported types](#supported-types)\n- [Supported keywords](#supported-keywords)\n\n\n## QuickStart\nAlthough this library is primarily developed for operators, it can be used anywhere you work with \nEnvironment Variables or `map[string]string`.\n\nThe great advantage of this library is its ease of use and the fact that it allows you to read the configuration from multiple \nsources without having to learn other libs. A few keywords will make it much easier for you to perform basic operations like \nsetting default values or forcing a value.\n\n### K8s Binder\nThe **ENV-GO-K8S-OPERATOR-BINDER/k8s** package is used to easily bind kubernetes annotations and labels into GO structures.\nEffectively it is about `map[string]string` configurations.\n\n\nImagine we have a resource that contains the following annotations (it works exactly the same for Labels).\n```yaml\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n  annotations:\n    company.example.io/strategy: failover\n    company.example.io/primary-geotags: us,za\n    company.example.io/ttl-seconds: \"30\"\n    company.example.io/autoscale: \"true\"\n    company.example.io/uid: \"eyJhbGciOiJ\"\n  name: ing\n```\n\n```golang\nimport \"github.com/AbsaOSS/go-k8s-operator-binder/k8smap\"\n\nvar settings = struct {\n    // binding required value\n    Type          string   `k8smap\"company.example.io/strategy, require=true\"`\n    // binding slice of strings\n    PrimaryGeoTag []string `k8smap:\"company.example.io/primary-geotags\"`\n    // if the configuration is missing, then set the default int value to 30 \n    TTLSeconds int         `k8smap:\"k8gb.io/dns-ttl-seconds, default=30\"`\n    // binding bool value\n    Autoscale bool         `k8smap:\"k8gb.io/autoscale\"` \n    // nested structure\n    Credentials struct{\n        // public nested protected with default test \n        UID       `k8smap:\"k8gb.io/uid, protected=true, default=test`\n        // private nested protected with default test\n        base64    `k8smap:\"k8gb.io/uid, protected=true, default=MMaBcDeFgH...`\n    }\n}{}\n\n  // Fetch resource instance\n  ing := \u0026netv1.Ingress{}\n  err := r.Get(ctx, req.NamespacedName, ing)\n  if err != nil {\n    // do Something\n  }\n  annotations = ing.GetAnnotations()\n\n  // binding \n  err = k8smap.Bind(annotations, \u0026settings)\n  if err != nil {\n    // do something\n  }\n```\nThis is all you need, the `settings` will contain the correct values loaded from the Annotations.\nKeywords like `protected` or `default` can be configured in various ways as well as various data-types, \nsee below in this documentation.\n\n### Environment variables binder\nThe **ENV-GO-K8S-OPERATOR-BINDER/env** package is used to easily bind environment variables to GO structures. The package \nis designed to be usable in the widest possible range of scenarios. Among other things, it supports variable prefixes \nand bindings to unexported arrays. Take a look at the following usage example:\n```golang\nimport \"github.com/AbsaOSS/go-k8s-operator-binder/env\"\n\ntype Endpoint struct {\n\tURL string `env:\"ENDPOINT_URL, require=true\"`\n}\n\ntype Config struct {\n\n\t// reading string value from NAME\n\tName string `env:\"NAME\"`\n\n\t// reuse an already bound env variable NAME\n\tDescription string `env:\"NAME\"`\n\n\t// reuse an already bound variable NAME, but replace only when name \n\t// was not set before\n\tAlternativeName string `env:\"NAME, protected=true\"`\n\n\t// reading int with 8080 as default value\n\tDefaultPort uint16 `env:\"PORT, default=8080\"`\n\n\t// reading slice of strings with default values\n\tRegions []string `env:\"REGIONS, default=[us-east-1,us-east-2,us-west-1]\"`\n\n\t// reading slice of strings from env var\n\tSubnets []string `env:\"SUBNETS, default=[10.0.0.0/24,192.168.1.0/24]\"`\n\t\n\t// default=[] ensures that if INTERVALS does not exist, \n\t// []int8{} is set instead of []int8{nil}\n\tInterval []uint8 `env:\"INTERVALS, default=[]\"`\n\n\t// nested structure\n\tCredentials struct {\n\n\t\t// binding required value\n\t\tKeyID string `env:\"ACCESS_KEY_ID, require=true\"`\n\n\t\t// binding to private field\n\t\tsecretKey string `env:\"SECRET_ACCESS_KEY, require=true\"`\n\t}\n\n\t// expected PRIMARY_ prefix in nested environment variables\n\tEndpoint1 Endpoint `env:\"PRIMARY\"`\n\n\t// expected FAILOVER_ prefix in nested environment variables\n\tEndpoint2 Endpoint `env:\"FAILOVER\"`\n\n\t// the field does not have a bind tag set, \n\t// so it will be ignored during bind\n\tArgs []string\n}\n\n\nfunc main() {\n\tdefer clean()\n\tos.Setenv(\"PRIMARY_ENDPOINT_URL\", \"https://ep1.cloud.example.com\")\n\tos.Setenv(\"FAILOVER_ENDPOINT_URL\", \"https://ep2.cloud.example.com\")\n\tos.Setenv(\"ACCESS_KEY_ID\", \"AKIAIOSFODNN7EXAMPLE\")\n\tos.Setenv(\"SECRET_ACCESS_KEY\", \"wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\")\n\tos.Setenv(\"NAME\", \"Hello from 12-factor\")\n\tos.Setenv(\"PORT\", \"9000\")\n\tos.Setenv(\"SUBNETS\", \"10.0.0.0/24,10.0.1.0/24, 10.1.0.0/24,  10.1.1.0/24\")\n\n\tc := \u0026Config{}\n\tc.AlternativeName = \"protected name\"\n\tc.Description = \"hello from ENV-BINDER\"\n\tif err := env.Bind(c); err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\tfmt.Println(JSONize(c))\n}\n\n```\nfunction main generates the following output:\n```json\n{\n  \"Name\": \"Hello from 12-factor\",\n  \"Description\": \"Hello from 12-factor\",\n  \"AlternativeName\": \"protected name\",\n  \"DefaultPort\": 9000,\n  \"Regions\": [\n    \"us-east-1\",\n    \"us-east-2\",\n    \"us-west-1\"\n  ],\n  \"Subnets\": [\n    \"10.0.0.0/24\",\n    \"10.0.1.0/24\",\n    \"10.1.0.0/24\",\n    \"10.1.1.0/24\"\n  ],\n  \"Interval\": [],\n  \"Credentials\": {\n    \"KeyID\": \"AKIAIOSFODNN7EXAMPLE\"\n  },\n  \"Endpoint1\": {\n    \"URL\": \"https://ep1.cloud.example.com\"\n  },\n  \"Endpoint2\": {\n    \"URL\": \"https://ep2.cloud.example.com\"\n  },\n  \"Args\": null\n}\n```\n\n## Supported types\n**GO-K8S-OPERATOR-BINDER** supports all types listed in the following table.  In addition, it should be noted that in the case\nof slices, **GO-K8S-OPERATOR-BINDER** creates an instance of an empty slice if the value of the environment variable is\ndeclared and its value is empty string. In this case **GO-K8S-OPERATOR-BINDER** returns an empty slice instead of the vulnerable nil.\n\n| primitive types | slices |\n|---|---|\n| `int`,`int8`,`int16`,`int32`,`int64` | `[]int`,`[]int8`,`[]int16`,`[]int32`,`[]int64` |\n| `float32`,`float64` | `[]float32`,`[]float64` |\n| `uint`,`uint8`,`uint16`,`uint32`,`uint64` | `[]uint`,`[]uint8`,`[]uint16`,`[]uint32`,`[]uint64` |\n| `bool` | `[]bool` |\n| `string` | `[]string` |\n\n## Supported keywords\nBesides the fact that **GO-K8S-OPERATOR-BINDER** works with private fields and can add prefixes to variable names, it\noperates with several keywords. The structure in the introductory section works with all types\nof these keywords.\n\n- `default` - the value specified in the default tag is used in case env variable does not exist. e.g:\n  `env: \"SUBNET\", default=10.0.1.0/24` or `env: \"ENV_SUBNETS\", default=[]` which will set an empty slice instead\n  of a vulnerable nil value in case `ENV_SUBNETS` does not exist.\n\n- `require` - if `require=true` then env variable must exist otherwise Bind function returns error\n\n- `protected` - if `protected=true` then, in case the field in the structure already has a set value , the\n  Bind function will not set it. Otherwise, bind will be applied to it.\n\nYou can combine individual tags freely: `env: \"ENV_SWITCHER\", default=[true, false, true], protected=true`\nis a perfectly valid configuration\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsaoss%2Fgo-k8s-operator-binder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabsaoss%2Fgo-k8s-operator-binder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabsaoss%2Fgo-k8s-operator-binder/lists"}