{"id":43678806,"url":"https://github.com/reconcilerio/dies","last_synced_at":"2026-02-05T01:22:11.962Z","repository":{"id":36982644,"uuid":"415966642","full_name":"reconcilerio/dies","owner":"reconcilerio","description":"immutable, fluent, builders for Kubernetes resources","archived":false,"fork":false,"pushed_at":"2025-12-18T01:34:46.000Z","size":4344,"stargazers_count":9,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-12-21T11:52:51.142Z","etag":null,"topics":["builder-pattern","fluent-api","immutable","kubernetes"],"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/reconcilerio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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":"2021-10-11T14:40:06.000Z","updated_at":"2025-12-18T01:32:49.000Z","dependencies_parsed_at":"2023-02-12T04:17:02.405Z","dependency_job_id":"78e39a6c-43f5-4a7a-a94d-0bc6f25e7244","html_url":"https://github.com/reconcilerio/dies","commit_stats":{"total_commits":95,"total_committers":5,"mean_commits":19.0,"dds":0.4526315789473684,"last_synced_commit":"1b2f39f4eb7e6af5559e0951702703e320321cff"},"previous_names":["reconcilerio/dies"],"tags_count":43,"template":false,"template_full_name":null,"purl":"pkg:github/reconcilerio/dies","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reconcilerio%2Fdies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reconcilerio%2Fdies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reconcilerio%2Fdies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reconcilerio%2Fdies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reconcilerio","download_url":"https://codeload.github.com/reconcilerio/dies/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reconcilerio%2Fdies/sbom","scorecard":{"id":767242,"data":{"date":"2025-08-11","repo":{"name":"github.com/reconcilerio/dies","commit":"54235270de0f43d02495b81d7fa31f5606941eab"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.2,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yaml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":5,"reason":"Found 14/25 approved changesets -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/reconcilerio/dies/ci.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yaml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/reconcilerio/dies/ci.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yaml:26: update your workflow using https://app.stepsecurity.io/secureworkflow/reconcilerio/dies/ci.yaml/main?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: branch 'main' does not require approvers","Warn: codeowners review is not required on branch 'main'","Info: status check found to merge onto on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 1 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T01:10:24.643Z","repository_id":36982644,"created_at":"2025-08-23T01:10:24.643Z","updated_at":"2025-08-23T01:10:24.643Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29105274,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-05T00:52:08.035Z","status":"ssl_error","status_checked_at":"2026-02-05T00:52:07.703Z","response_time":62,"last_error":"SSL_read: 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":["builder-pattern","fluent-api","immutable","kubernetes"],"created_at":"2026-02-05T01:22:06.971Z","updated_at":"2026-02-05T01:22:11.949Z","avatar_url":"https://github.com/reconcilerio.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Dies - immutable, fluent, builders for Kubernetes resources \u003c!-- omit in toc --\u003e\n\n![CI](https://github.com/reconcilerio/dies/workflows/CI/badge.svg?branch=main)\n[![codecov](https://codecov.io/gh/reconcilerio/dies/branch/main/graph/badge.svg?token=vyXLcPBdV3)](https://codecov.io/gh/reconcilerio/dies)\n[![Go Reference](https://pkg.go.dev/badge/reconciler.io/dies.svg)](https://pkg.go.dev/reconciler.io/dies)\n[![Go Report Card](https://goreportcard.com/badge/reconciler.io/dies)](https://goreportcard.com/report/reconciler.io/dies)\n[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)\n\n- [Using dies](#using-dies)\n  - [Common methods](#common-methods)\n  - [Helper methods](#helper-methods)\n    - [k8s.io/apimachinery/pkg/util/intstr#IntOrString](#k8sioapimachinerypkgutilintstrintorstring)\n    - [k8s.io/apimachinery/pkg/api/resource#Quantity](#k8sioapimachinerypkgapiresourcequantity)\n    - [k8s.io/api/core/v1#ResourceList](#k8sioapicorev1resourcelist)\n- [Creating dies](#creating-dies)\n  - [diegen](#diegen)\n  - [die markers](#die-markers)\n    - [+die](#die)\n    - [+die:field](#diefield)\n- [Community](#community)\n  - [Code of Conduct](#code-of-conduct)\n  - [Communication](#communication)\n  - [Contributing](#contributing)\n- [Acknowledgements](#acknowledgements)\n- [License](#license)\n\n---\n\nThis project contains dies for many of the most common built-in Kubernetes types, and tools to create dies for custom resources.\n\n## Using dies\n\nDies start with a blank object that is stamped to add state. All dies are immutable, each stamping returns a new instance containing the mutated state while the original instance is not modified.\n\n```go\nimport (\n    appsv1 \"k8s.io/api/apps/v1\"\n    corev1 \"k8s.io/api/core/v1\"\n    metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n    dieappsv1 \"reconciler.io/dies/apis/apps/v1\"\n    diecorev1 \"reconciler.io/dies/apis/core/v1\"\n    diemetav1 \"reconciler.io/dies/apis/meta/v1\"\n)\n```\n\n```go\ndie := dieappsv1.DeploymentBlank.\n    MetadataDie(func(d *diemetav1.ObjectMetaDie) {\n        d.Name(\"my-name\")\n    }).\n    SpecDie(func(d *dieappsv1.DeploymentSpecDie) {\n        d.TemplateDie(func(d *diecorev1.PodTemplateSpecDie) {\n            d.SpecDie(func(d *diecorev1.PodSpecDie) {\n                d.ContainerDie(\"app\", func(d *diecorev1.ContainerDie) {\n                    d.Image(\"registry.example/image:latest\")\n                    d.EnvDie(\"MY_VAR\", func(d *diecorev1.EnvVarDie) {\n                        d.Value(\"my-value\")\n                    })\n                })\n            })\n        })\n    })\ndeployment := die.DieRelease()\n```\n\nIs equivalent to:\n\n```go\ndeployment := \u0026appsv1.Deployment{\n    ObjectMeta: metav1.ObjectMeta{\n        Name: \"my-name\",\n    },\n    Spec: appsv1.DeploymentSpec{\n        Template: corev1.PodTemplateSpec{\n            Spec: corev1.PodSpec{\n                Containers: []corev1.Container{\n                    {\n                        Name:  \"app\",\n                        Image: \"registry.example/image:latest\",\n                        Env:   []corev1.EnvVar{\n                            {\n                                Name: \"MY_VAR\",\n                                Value: \"my-value\",\n                            },\n                        },\n                    },\n                },\n            },\n        },\n    },\n}\n```\n\nUnlike when defining an instance of a struct, the die can be captured in an intermediate state with mutations applied incrementally. This behavior is particularly useful for tests that use a common object base with individual mutations applied.\n\n```go\naltDeployment := die.\n    SpecDie(func(d *dieappsv1.DeploymentSpecDie) {\n        d.TemplateDie(func(d *diecorev1.PodTemplateSpecDie) {\n            d.SpecDie(func(d *diecorev1.PodSpecDie) {\n                d.ContainerDie(\"app\", func(d *diecorev1.ContainerDie) {\n                    d.EnvDie(\"MY_VAR\", func(d *diecorev1.EnvVarDie) {\n                        d.Value(\"some-other-value\")\n                    })\n                })\n            })\n        })\n    }).DieRelease())\n```\n\nWhile the outer die is immutable, returning a new die for each call that can be chained together. The dies passed to callbacks are mutable.\n\nAdditional methods will be added to dies over time to make common operations easier and safer.\n\n### Common methods\n\n```go\n// for managed type `MyResource`\n\n// MyResourceBlank is an empty die that mutations can be stamped from. All die blanks\n// are immutable.\nvar MyResourceBlank *MyResourceDie\n\ntype MyResourceDie interface {\n    // DieStamp returns a new die with the resource passed to the callback\n    // function. The resource is mutable.\n    DieStamp(fn func(r *MyResource)) *MyResourceDie\n\n    // Experimental: DieStampAt uses a JSON path (http://goessner.net/articles/JsonPath/)\n    // expression to stamp portions of the resource. The callback is invoked with each\n    // JSON path match. Panics if the callback function does not accept a single argument\n    // of the same type or a pointer to that type as found on the resource at the target\n    // location.\n    //\n    // Future iterations will improve type coercion from the resource to the callback\n    // argument.\n    DieStampAt(jp string, fn interface{}) *MyResourceDie\n\n    // DieFeed returns a new die with the provided resource.\n    DieFeed(r MyResource) *MyResourceDie\n\n    // DieFeedPtr returns a new die with the provided resource pointer. If the\n    // resource is nil, the empty value is used instead.\n    DieFeedPtr(r *MyResource) *MyResourceDie\n\n    // DieFeedDuck returns a new die with the provided value converted into the underlying type. Panics on error.\n    DieFeedDuck(v any) *MyResourceDie\n\n    // DieFeedJSON returns a new die with the provided JSON. Panics on error.\n    DieFeedJSON(j []byte) *MyResourceDie\n\n    // DieFeedYAML returns a new die with the provided YAML. Panics on error.\n    DieFeedYAML(y []byte) *MyResourceDie\n\n    // DieFeedYAMLFile returns a new die loading YAML from a file path. Panics on error.\n    DieFeedYAMLFile(name string) *MyResourceDie\n\n    // DieFeedRawExtension returns a new die with the provided raw extension. Panics on error.\n    DieFeedRawExtension(raw runtime.RawExtension) *MyResourceDie\n\n    // DieRelease returns the resource managed by the die.\n    DieRelease() MyResource\n\n    // DieReleasePtr returns a pointer to the resource managed by the die.\n    DieReleasePtr() *MyResource\n\n\t// DieReleaseDuck releases the value into the passed value and returns the same. Panics on error.\n\tDieReleaseDuck(v any) any\n\n    // DieReleaseJSON returns the resource managed by the die as JSON. Panics on error.\n    DieReleaseJSON() []byte\n\n    // DieReleaseYAML returns the resource managed by the die as YAML. Panics on error.\n    DieReleaseYAML() []byte\n\n    // DieReleaseRawExtension returns the resource managed by the die as an\n    // raw extension. Panics on error.\n    DieReleaseRawExtension() runtime.RawExtension\n\n    // DieImmutable returns a new die for the current die's state that is\n    // either mutable (`false`) or immutable (`true`). \n    DieImmutable(immutable bool) *MyResourceDie\n\n    // DieWith returns a new die after passing the current die to the callback\n    // function. The passed die is mutable.\n    DieWith(fn ...func(d *MyResourceDie)) *MyResourceDie\n\n    // DieSeal returns a new die for the current die's state that is sealed for comparison in future diff and patch operations.\n    DieSeal() *MyResourceDie\n\n    // DieSealFeed returns a new die for the current die's state that uses a specific resource for comparison in future diff and patch operations.\n    DieSealFeed(r MyResource) *MyResourceDie\n\n    // DieSealFeedPtr returns a new die for the current die's state that uses a specific resource for comparison in future diff and patch operations.\n    DieSealFeedPtr(r *MyResource) *MyResourceDie\n\n    // DieSealRelease returns the sealed resource managed by the die.\n    DieSealRelease() MyResource\n\n    // DieSealReleasePtr returns the sealed resource pointer managed by the die.\n    DieSealReleasePtr() *MyResource\n\n    // DieDiff uses cmp.Diff to compare the current value of the die with the sealed value.\n    DieDiff(opts ...cmp.Option) string\n\n    // DiePatch generates a patch between the current value of the die and the sealed value.\n    DiePatch(patchType types.PatchType) ([]byte, error)\n\n    // DeepCopy returns a new die with equivalent state. Useful for\n    // snapshotting a mutable die.\n    DeepCopy() *MyResourceDie\n}\n```\n\nFor each exported field `MyField` on `MyResource`, a method is registered to set that field.\n\n```go\ntype MyResourceDie interface {\n    // continued\n\n    MyField(*MyResource) *MyResourceDie\n}\n```\n\nDies marked as implementing `metav1.Object` and `runtime.Object`  generate\nadditional methods.\n\n```go\nimport (\n    metav1 \"k8s.io/apimachinery/pkg/apis/meta/v1\"\n    runtime \"k8s.io/apimachinery/pkg/runtime\"\n)\n\ntype MyResourceDie interface {\n    // continued\n\n    runtime.Object\n    metav1.Object\n    metav1.ObjectMetaAccessor\n\n    // DieReleaseUnstructured returns the resource managed by the die as an\n    // unstructured object.\n    DieReleaseUnstructured() *unstructured.Unstructured\n\n    // DieDefaultTypeMetadata sets the APIVersion and Kind\n    DieDefaultTypeMetadata() *MyResourceDie\n\n    // APIVersion defines the versioned schema of this representation of an\n    // object. Servers should convert recognized schemas to the latest internal\n    // value, and may reject unrecognized values. More info:\n    // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources\n    APIVersion(v string) *MyResourceDie\n\n    // Kind is a string value representing the REST resource this object\n    // represents. Servers may infer this from the endpoint the client submits\n    // requests to. Cannot be updated. In CamelCase. More info:\n    // https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds\n    Kind(v string) *MyResourceDie\n\n    // TypeMetadata standard object's type metadata.\n    TypeMetadata(v metav1.TypeMeta) *MyResourceDie\n\n    // TypeMetaDie stamps the resource's TypeMeta field with a mutable die.\n    TypeMetaDie(fn func(d *diemetav1.TypeMetaDie)) *MyResourceDie\n\n    // Metadata standard object's metadata.\n    Metadata(v metav1.ObjectMeta) *MyResourceDie\n\n    // MetadataDie stamps the resource's ObjectMeta field with a mutable die.\n    MetadataDie(fn func(d *diemetav1.ObjectMetaDie)) *MyResourceDie\n\n    // SpecDie stamps the resource's spec field with a mutable die. This method\n    // is only created if `MyResourceSpecDie` is defined.\n    SpecDie(fn func(d *MyResourceSpecDie)) *MyResourceDie\n\n    // StatusDie stamps the resource's status field with a mutable die. This\n    // method is only created if `MyResourceStatusDie` is defined.\n    StatusDie(fn func(d *MyResourceStatusDie)) *MyResourceDie\n}\n```\n\n### Helper methods\n\nEach exported field on the resource backing the die has a setter method defined. Some types offer additional helper methods to make common conversions easier.\n\n####  k8s.io/apimachinery/pkg/util/intstr#IntOrString\n\n```go\ntype MyResourceDie interface {\n    // continued\n\n    Port(port intstr.IntOrString) *MyResourceDie\n\n    // PortInt sets Port with the int value.\n    PortInt(port int) *MyResourceDie\n\n    // PortString sets Port with the string value.\n    PortString(port string) *MyResourceDie\n}\n```\n\n#### k8s.io/apimachinery/pkg/api/resource#Quantity\n\n```go\ntype MyResourceDie interface {\n    // continued\n\n    Memory(memory resource.Quantity) *MyResourceDie\n\n    // MemoryString sets Memory by parsing the string as a Quantity. Panics if\n    // the string is not parsable.\n    MemoryString(memory string) *MyResourceDie\n}\n```\n\n#### k8s.io/api/core/v1#ResourceList\n\n```go\ntype MyResourceDie interface {\n    // continued\n\n    Limits(limits corev1.ResourceList) *MyResourceDie\n\n    // AddLimit sets a single quantity on the Limits resource list.\n    AddLimit(name string, limit resource.Quantity) *MyResourceDie\n\n    // AddLimitString parses the quantity setting a single value on the Limits\n    // resource list. Panics if the string is not parsable.\n    AddLimitString(name string, limit string) *MyResourceDie\n}\n\n```\n\n## Creating dies\n\nDies are primarily generated for types from [die markers](#die-markers) using\n[`diegen`](#diegen).\n\nAdditional methods can be added to a die to enrich its behavior. Each additional method is added to the die struct.\n\nExample dispatching to a nested die to managed the template\n`corev1.PodTemplateSpec` for `DeploymentSpec`:\n\n```go\nfunc (d *DeploymentSpecDie) TemplateDie(fn func(d *diecorev1.PodTemplateSpecDie)) *DeploymentSpecDie {\n    return d.DieStamp(func(r *appsv1.DeploymentSpec) {\n        d := diecorev1.PodTemplateSpecBlank.\n            DieImmutable(false).\n            DieFeed(r.Template)\n        fn(d)\n        r.Template = d.DieRelease()\n    })\n}\n```\n\nExample adapting `metav1.Condition` dies to `appsv1.DeploymentCondition`:\n\n```go\nfunc (d *DeploymentStatusDie) ConditionsDie(conditions ...*diemetav1.ConditionDie) *DeploymentStatusDie {\n    return d.DieStamp(func(r *appsv1.DeploymentStatus) {\n        r.Conditions = make([]appsv1.DeploymentCondition, len(conditions))\n        for i := range conditions {\n            c := conditions[i].DieRelease()\n            // coerce metav1.Condition to appsv1.DeploymentCondition\n            r.Conditions[i] = appsv1.DeploymentCondition{\n                Type:               appsv1.DeploymentConditionType(c.Type),\n                Status:             corev1.ConditionStatus(c.Status),\n                Reason:             c.Reason,\n                Message:            c.Message,\n                LastTransitionTime: c.LastTransitionTime,\n            }\n        }\n    })\n}\n```\n\n\n\n### diegen\n\nInstall diegen:\n\n```sg\ngo install reconciler.io/dies/diegen\n```\n\nCreate or update the generated dies:\n\n```sh\ndiegen die:headerFile=\"hack/boilerplate.go.txt\" paths=\"./...\"\n```\n\nAll generated content is created within `zz_generated.die.go` and `zz_generated.die_test.go` in each package where die markers are found.\n\n### die markers\n\n#### +die\n\n```go\nimport (\n    appsv1 \"k8s.io/api/apps/v1\"\n)\n\n// +die:object=true,apiVersion=apps/v1,kind=Deployment\ntype _ = appsv1.Deployment\n\n// +die\ntype _ = appsv1.DeploymentSpec\n\n// +die\ntype _ = appsv1.DeploymentStatus\n```\n\nFor packages you control, dies can be created in the same package as the resource they model by adding the markers to existing types.\n\n```go\n// +die:object=true,apiVersion=example.reconciler.io/v1,kind=MyResource\ntype MyResource struct {\n    metav1.TypeMeta   `json:\",inline\"`\n    metav1.ObjectMeta `json:\"metadata,omitempty\"`\n\n    Spec MyResourceSpec `json:\"spec\"`\n    // +optional\n    Status MyResourceStatus `json:\"status\"`\n}\n\n// +die\ntype MyResourceSpec struct {\n    // add fields\n}\n\n// +die\ntype MyResourceStatus struct {\n    // add fields\n}\n```\n\nProperties:\n- **object** `bool` (optional): indicates the target type implements `metav1.Object` and `runtime.Object`\n- **apiVersion** `string` (optional): defaults the blanks die's APIVersion (only for objects)\n- **kind** `string` (optional): defaults the blank die's Kind (only for objects)\n- **ignore** `[]string` (optional): set of fields to ignore on the type\n\n#### +die:field\n\n```go\n// +die\n// +die:field:name=Selector,package=reconciler.io/dies/apis/meta/v1,die=LabelSelectorDie,pointer=true\n// +die:field:name=Template,package=reconciler.io/dies/apis/core/v1,die=PodTemplateSpecDie\ntype MyResourceSpec struct {\n    Selector *metav1.LabelSelector  `json:\"selector`\"\n    Template corev1.PodTemplateSpec `json:\"template\"`\n}\n```\n\nResults in the standard die method and two additional mutation methods for the defined fields:\n\n```go\n// SelectorDie mutates Selector as a die\n//\n// Label selector for pods. It must match the pod template's labels.\nfunc (d *MyResourceSpecDie) SelectorDie(fn func(d *metav1.LabelSelectorDie)) *MyResourceSpecDie {\n\treturn d.DieStamp(func(r *appsv1.DeploymentSpec) {\n\t\td := metav1.LabelSelectorBlank.DieImmutable(false).DieFeedPtr(r.Selector)\n\t\tfn(d)\n\t\tr.Selector = d.DieReleasePtr()\n\t})\n}\n\n// TemplateDie mutates Template as a die\n//\n// Template describes the pods that will be created.\nfunc (d *MyResourceSpecDie) TemplateDie(fn func(d *corev1.PodTemplateSpecDie)) *MyResourceSpecDie {\n\treturn d.DieStamp(func(r *appsv1.DeploymentSpec) {\n\t\td := corev1.PodTemplateSpecBlank.DieImmutable(false).DieFeed(r.Template)\n\t\tfn(d)\n\t\tr.Template = d.DieRelease()\n\t})\n}\n```\n\nMutation methods for fields backed by slices require additional metadata. Depending on the content of the list it the whole listing can be replaced, or a single item in the list can be mutated.\n\nAtomic lists cannot be mutated incrementally, the whole content is replaced. This pattern is common where there is no unique field inside the list to find a specific entry for.\n\n```go\n// +die:field:name=Ports,die=ContainerPortDie,listType=atomic\n```\n\n```go\n// PortsDie replaces Ports by collecting the released value from each die passed.\nfunc (d *ContainerDie) PortsDie(ports ...*ContainerPortDie) *ContainerDie {\n\t...snip...\n}\n```\n[Full source](https://pkg.go.dev/reconciler.io/dies/apis/core/v1#ContainerDie.PortsDie)\n\nThe env field is a map list type with the default key. The named env var in the list will be loaded into the EnvVarDie and passed to the callback with the mutated value updated in the slice.\n\nBecause a single item is mutated the method name uses a singular form. If the conversion from plural to singular produces a non-ideal name, the default method name can be overridden with the **method** parameter.\n\n```go\n// +die:field:name=Env,die=EnvSourceDie,listType=map\n```\n\n```go\n// EnvDie mutates a single item in Env matched by the nested field Name, appending a new item if no match is found.\nfunc (d *ContainerDie) EnvDie(name string, fn func(d *EnvVarDie)) *ContainerDie {\n    ...snip...\n}\n```\n[Full source](https://pkg.go.dev/reconciler.io/dies/apis/core/v1#ContainerDie.EnvDie)\n\nThe env from field is a map list type with a custom key. The default map key is `Name`.\n\n```go\n// +die:field:name=EnvFrom,die=EnvFromSourceDie,listType=map,listMapKey=Prefix\n```\n\n```go\n// EnvFromDie mutates a single item in EnvFrom matched by the nested field Prefix, appending a new item if no match is found.\nfunc (d *ContainerDie) EnvFromDie(prefix string, fn func(d *EnvFromSourceDie)) *ContainerDie {\n    ...snip...\n}\n```\n[Full source](https://pkg.go.dev/reconciler.io/dies/apis/core/v1#ContainerDie.EnvFromDie)\n\n\nThe resize policy field is also a map list type, but the map key field is defined with a custom type.\n\n```go\n// +die:field:name=ResizePolicy,die=ContainerResizePolicyDie,listType=map,listMapKey=ResourceName,listMapKeyPackage=k8s.io/api/core/v1,listMapKeyType=ResourceName\n```\n\n```go\n// ResizePolicyDie mutates a single item in ResizePolicy matched by the nested field ResourceName, appending a new item if no match is found.\nfunc (d *ContainerDie) ResizePolicyDie(resourceName corev1.ResourceName, fn func(d *ContainerResizePolicyDie)) *ContainerDie {\n    ...snip...\n}\n```\n[Full source](https://pkg.go.dev/reconciler.io/dies/apis/core/v1#ContainerDie.ResizePolicyDie)\n\n\nProperties:\n- **name** `string`: name of the field on the target resource to mutate\n- **method** `string` (optional): name of the generated mutation method on the host die (defaults to the name with \"Die\" appended, for list type map the name is made singular)\n- **package** `string` (optional): go package containing the target die and blank. `_/` is an alias to the package prefix for the built in dies, for example `_/core/v1` expands to `reconciler.io/dies/apis/core/v1`.\n- **die** `string`: go type for the die backing the field's struct\n- **blank** `string` (optional): go type for a blank of the die's type (defaults to the die replacing the \"Die\" suffix with \"Blank\")\n- **pointer** `bool` (optional): the field is defined as a pointer reference, uses DieFeedPtr and DieReleasePtr\n- **listType** `string` (optional):\n  - ``: field is not a list (default)\n  - `map`: a single value in the list is mutated, or a new item appended\n  - `atomic`: the list is replaced\n- **listMapKey** `string` (optional): defaults to `Name` for map list types (only for list type map)\n- **listMapKeyPackage** `string` (optional): the go package containing the type representing the key field on the target struct, defaults to the current package (only for list type map)\n- **listMapKeyType** `string` (optional): the go type representing the key field on the target struct, defaults to `string` (only for list type map)\n\n## Community\n\n### Code of Conduct\n\nThe reconciler.io projects follow the [Contributor Covenant Code of Conduct](./CODE_OF_CONDUCT.md). In short, be kind and treat others with respect.\n\n### Communication\n\nGeneral discussion and questions about the project can occur either on the Kubernetes Slack [#reconcilerio](https://kubernetes.slack.com/archives/C07J5G9NDHR) channel, or in the project's [GitHub discussions](https://github.com/orgs/reconcilerio/discussions). Use the channel you find most comfortable.\n\n### Contributing\n\nThe reconciler.io dies project team welcomes contributions from the community. A contributor license agreement (CLA) is not required. You own full rights to your contribution and agree to license the work to the community under the Apache License v2.0, via a [Developer Certificate of Origin (DCO)](https://developercertificate.org). For more detailed information, refer to [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Acknowledgements\n\n`dies` was conceived by [Scott Andrews](https://github.com/scothis) drawing inspiration from previous work in [`reconciler.io/runtime`](https://github.com/reconcilerio/runtime/).\n\n## License\n\nApache License v2.0: see [LICENSE](./LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freconcilerio%2Fdies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freconcilerio%2Fdies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freconcilerio%2Fdies/lists"}