1"use strict";(globalThis.webpackChunkratify=globalThis.webpackChunkratify||[]).push([[2198],{28453(e,n,s){s.d(n,{R:()=>t,x:()=>c});var r=s(96540);const o={},i=r.createContext(o);function t(e){const n=r.useContext(i);return r.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:t(e.components),r.createElement(i.Provider,{value:n},e.children)}},75038(e,n,s){s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>a});const r=JSON.parse('{"id":"reference/custom resources/api-upgrade-instruction","title":"API Upgrade Instructions","description":"It\'s normal and inevitable to move CRD APIs to newer versions as the project","source":"@site/versioned_docs/version-1.2/reference/custom resources/api-upgrade-instruction.md","sourceDirName":"reference/custom resources","slug":"/reference/custom resources/api-upgrade-instruction","permalink":"/docs/1.2/reference/custom resources/api-upgrade-instruction","draft":false,"unlisted":false,"editUrl":"https://github.com/ratify-project/ratify-web/blob/main/versioned_docs/version-1.2/reference/custom resources/api-upgrade-instruction.md","tags":[],"version":"1.2","frontMatter":{},"sidebar":"tutorialSidebar","previous":{"title":"Caching in Ratify","permalink":"/docs/1.2/reference/cache"},"next":{"title":"Certificate Store (Deprecated)","permalink":"/docs/1.2/reference/custom resources/certificate-stores"}}');var o=s(74848),i=s(28453);const t={},c="API Upgrade Instructions",d={},a=[{value:"Upgrade steps from <code>v1alpha1</code> to <code>v1beta1</code>",id:"upgrade-steps-from-v1alpha1-to-v1beta1",level:2},{value:"Additional steps while incompatibilities introduced",id:"additional-steps-while-incompatibilities-introduced",level:2},{value:"Upgrade existing objects to a new stored version",id:"upgrade-existing-objects-to-a-new-stored-version",level:2},{value:"References",id:"references",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"api-upgrade-instructions",children:"API Upgrade Instructions"})}),"\n",(0,o.jsxs)(n.p,{children:["It's normal and inevitable to move CRD APIs to newer versions as the project\nmoves to a more stable stage. This doc lists the steps for the first version\nbump-up from ",(0,o.jsx)(n.code,{children:"v1alpha1"})," to ",(0,o.jsx)(n.code,{children:"v1beta1"}),", which can be referenced when we need to have\nnew API versions in the future."]}),"\n",(0,o.jsxs)(n.h2,{id:"upgrade-steps-from-v1alpha1-to-v1beta1",children:["Upgrade steps from ",(0,o.jsx)(n.code,{children:"v1alpha1"})," to ",(0,o.jsx)(n.code,{children:"v1beta1"})]}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:['Controller-runtime models conversion between versions in terms of a\n"hub and spoke" model. In Ratify, we mark the ',(0,o.jsx)(n.code,{children:"unversioned"})," as the hub version,\nother versions(",(0,o.jsx)(n.code,{children:"v1alpha1"})," and ",(0,o.jsx)(n.code,{children:"v1beta1"}),") as spoke versions. New versions would\nbe added as spoke versions."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Create new API version by ",(0,o.jsx)(n.code,{children:"kubebuilder"})," command:"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-bash",children:"kubebuilder create api --group config.ratify.deislabs.io --version v1beta1 --kind <kind>\n"})}),"\n",(0,o.jsxs)(n.p,{children:["kind could be ",(0,o.jsx)(n.code,{children:"Store"}),", ",(0,o.jsx)(n.code,{children:"Verifier"})," and ",(0,o.jsx)(n.code,{children:"CertificateStore"})," respectively."]}),"\n",(0,o.jsxs)(n.ol,{start:"3",children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Copy over existing types from ",(0,o.jsx)(n.code,{children:"v1alpha1"})," to ",(0,o.jsx)(n.code,{children:"v1beta1"}),"."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Create an ",(0,o.jsx)(n.code,{children:"unversioned"})," API by manually copying the existing types from ",(0,o.jsx)(n.code,{children:"v1alpha1"})," to\n",(0,o.jsx)(n.code,{children:"unversioned"})," as ",(0,o.jsx)(n.code,{children:"kubebuilder"})," doesn't support ",(0,o.jsx)(n.code,{children:"unversioned"})," as version value."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In each spoke version package, add marker ",(0,o.jsx)(n.code,{children:"+k8s:conversion-gen"})," directive\npointing to the hub(",(0,o.jsx)(n.code,{children:"unversioned"}),") version, which must be in ",(0,o.jsx)(n.code,{children:"doc.go"}),". Example:"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"// +k8s:conversion-gen=github.com/deislabs/ratify/api/unversioned\npackage v1alpha1\n"})}),"\n",(0,o.jsxs)(n.ol,{start:"6",children:["\n",(0,o.jsxs)(n.li,{children:["In hub(",(0,o.jsx)(n.code,{children:"unversioned"}),") version package, create ",(0,o.jsx)(n.code,{children:"doc.go"})," and add marker ",(0,o.jsx)(n.code,{children:"+kubebuilder:object:generate=true"})," so that the object generator can use it. Example:"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:"package unversioned\n// +kubebuilder:object:generate=true\n"})}),"\n",(0,o.jsxs)(n.ol,{start:"7",children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In spoke version packages, add a ",(0,o.jsx)(n.code,{children:"localSchemeBuilder = runtime.NewSchemeBuilder(SchemeBuilder.AddToScheme)"})," in ",(0,o.jsx)(n.code,{children:"groupversion_info.go"})," so the auto-generated code\ncould compile."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["In hub(",(0,o.jsx)(n.code,{children:"unversioned"}),") version package, add marker ",(0,o.jsx)(n.code,{children:"+kubebuilder:skip"})," to each\nAPI and remove all other markers so that skip kubebuilder processing it."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Mark ",(0,o.jsx)(n.code,{children:"v1beta1"})," as the storage version by adding marker ",(0,o.jsx)(n.code,{children:"+kubebuilder:storageversion"}),"\nto the root types. Example:"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'// +kubebuilder:object:root=true\n// +kubebuilder:resource:scope="Cluster"\n// +kubebuilder:storageversion\n// Store is the Schema for the stores API\ntype Store struct {\n\tmetav1.TypeMeta `json:",inline"`\n\tmetav1.ObjectMeta `json:"metadata,omitempty"`\n\n\tSpec StoreSpec `json:"spec,omitempty"`\n\tStatus StoreStatus `json:"status,omitempty"`\n}\n'})}),"\n",(0,o.jsxs)(n.ol,{start:"10",children:["\n",(0,o.jsxs)(n.li,{children:["In the outdated spoke version package, add marker ",(0,o.jsx)(n.code,{children:"+kubebuilder:deprecatedversion:warning=<msg>"})," to the root type of each API. Example:"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'// +kubebuilder:object:root=true\n// +kubebuilder:resource:scope="Cluster"\n// +kubebuilder:deprecatedversion:warning="v1alpha1 of the Store API has been deprecated. Please migrate to v1beta1."\n// Store is the Schema for the stores API\ntype Store struct {\n\tmetav1.TypeMeta `json:",inline"`\n\tmetav1.ObjectMeta `json:"metadata,omitempty"`\n\tSpec StoreSpec `json:"spec,omitempty"`\n\tStatus StoreStatus `json:"status,omitempty"`\n}\n'})}),"\n",(0,o.jsxs)(n.ol,{start:"11",children:["\n",(0,o.jsxs)(n.li,{children:["Run ",(0,o.jsx)(n.code,{children:"make manifests generate"})," to generate CRD objects, DeepCopy methods and conversion methods. ",(0,o.jsx)(n.code,{children:"zz_generated.conversion.go"})," and ",(0,o.jsx)(n.code,{children:"zz_generated.deepcopy.go"}),"\nwould be generated in each spoke version package."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"additional-steps-while-incompatibilities-introduced",children:"Additional steps while incompatibilities introduced"}),"\n",(0,o.jsxs)(n.p,{children:["There is no real change between ",(0,o.jsx)(n.code,{children:"v1alpha1"})," and ",(0,o.jsx)(n.code,{children:"v1beta1"}),", which makes it easier\nthan making incompatible upgrade. If there is an incompatible change introduced\nin a new version, we could follow the above 11 steps first and then follow the\nbelow instruction. Let's take the example of adding a new ",(0,o.jsx)(n.code,{children:"Test"})," field to ",(0,o.jsx)(n.code,{children:"StoreSpec"}),"."]}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["Add a string field ",(0,o.jsx)(n.code,{children:"Test"})," to ",(0,o.jsx)(n.code,{children:"StoreSpec"})," in both ",(0,o.jsx)(n.code,{children:"unversioned"})," and new version(",(0,o.jsx)(n.code,{children:"v1beta1"}),") packages."]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:["After executing ",(0,o.jsx)(n.code,{children:"make manifests generate"}),", we would get errors similar to:"]}),"\n"]}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{children:"E0308 02:20:37.752749 4053005 conversion.go:756] Warning: could not find nor generate a final Conversion function for github.com/deislabs/ratify/api/unversioned.StoreSpec -> github.com/binbin-li/ratify/api/v1alpha1.StoreSpec\nE0308 02:20:37.752867 4053005 conversion.go:757] the following fields need manual conversion:\nE0308 02:20:37.752874 4053005 conversion.go:759] - Test\n"})}),"\n",(0,o.jsxs)(n.p,{children:["It means that we need to manually implement the conversion method from ",(0,o.jsx)(n.code,{children:"unversioned"}),"\nto ",(0,o.jsx)(n.code,{children:"v1alpha1"}),"."]}),"\n",(0,o.jsxs)(n.ol,{start:"3",children:["\n",(0,o.jsxs)(n.li,{children:["Check the generated ",(0,o.jsx)(n.code,{children:"zz_generated.conversion.go"})," in ",(0,o.jsx)(n.code,{children:"v1alpha1"})," package, we\ncould see errors indicating that ",(0,o.jsx)(n.code,{children:"Convert_unversioned_StoreSpec_To_v1alpha1_StoreSpec()"}),"\nwas not declared. Now we could create a new file ",(0,o.jsx)(n.code,{children:"store_conversion.go"})," in ",(0,o.jsx)(n.code,{children:"v1alpha1"}),"\npackage, and implement this method manually there to resolve the error."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"upgrade-existing-objects-to-a-new-stored-version",children:"Upgrade existing objects to a new stored version"}),"\n",(0,o.jsxs)(n.p,{children:["It's safe to use both the old and new versions after upgraded. But if we really\nwant to migrate stored objects to the new version, please follow the instruction:\n",(0,o.jsx)(n.a,{href:"https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definition-versioning/#upgrade-existing-objects-to-a-new-stored-version",children:"Upgrade existing objects to a new stored version"})]}),"\n",(0,o.jsx)(n.h2,{id:"references",children:"References"}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://book.kubebuilder.io/multiversion-tutorial/api-changes.html",children:"Kubebuilder tutorial on multi-version API"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://cluster-api-ibmcloud.sigs.k8s.io/developer/conversion.html",children:"Guide for API conversions"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://github.com/kubernetes-sigs/kubebuilder/issues/1529#issuecomment-656359330",children:"Approach to using conversion-gen with multi-versioning"})}),"\n",(0,o.jsx)(n.p,{children:(0,o.jsx)(n.a,{href:"https://github.com/Azure/eraser/pull/544",children:"Example PR following same steps"})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.