mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Add apply subresource support to client-go's typed client
This commit is contained in:
parent
f137c47770
commit
29423501f0
@ -37,6 +37,7 @@ import (
|
|||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
appsv1apply "k8s.io/client-go/applyconfigurations/apps/v1"
|
appsv1apply "k8s.io/client-go/applyconfigurations/apps/v1"
|
||||||
|
appsv1autoscaling "k8s.io/client-go/applyconfigurations/autoscaling/v1"
|
||||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1"
|
appsv1client "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||||
@ -266,6 +267,10 @@ func (c conversionClient) UpdateScale(ctx context.Context, name string, scale *a
|
|||||||
return nil, errors.New("UpdateScale() is not implemented for conversionClient")
|
return nil, errors.New("UpdateScale() is not implemented for conversionClient")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c conversionClient) ApplyScale(ctx context.Context, name string, scale *appsv1autoscaling.ScaleApplyConfiguration, opts metav1.ApplyOptions) (*autoscalingv1.Scale, error) {
|
||||||
|
return nil, errors.New("ApplyScale() is not implemented for conversionClient")
|
||||||
|
}
|
||||||
|
|
||||||
func convertSlice(rcList []*v1.ReplicationController) ([]*apps.ReplicaSet, error) {
|
func convertSlice(rcList []*v1.ReplicationController) ([]*apps.ReplicaSet, error) {
|
||||||
rsList := make([]*apps.ReplicaSet, 0, len(rcList))
|
rsList := make([]*apps.ReplicaSet, 0, len(rcList))
|
||||||
for _, rc := range rcList {
|
for _, rc := range rcList {
|
||||||
|
@ -279,6 +279,12 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
|||||||
return &applyconfigurationsautoscalingv1.HorizontalPodAutoscalerSpecApplyConfiguration{}
|
return &applyconfigurationsautoscalingv1.HorizontalPodAutoscalerSpecApplyConfiguration{}
|
||||||
case autoscalingv1.SchemeGroupVersion.WithKind("HorizontalPodAutoscalerStatus"):
|
case autoscalingv1.SchemeGroupVersion.WithKind("HorizontalPodAutoscalerStatus"):
|
||||||
return &applyconfigurationsautoscalingv1.HorizontalPodAutoscalerStatusApplyConfiguration{}
|
return &applyconfigurationsautoscalingv1.HorizontalPodAutoscalerStatusApplyConfiguration{}
|
||||||
|
case autoscalingv1.SchemeGroupVersion.WithKind("Scale"):
|
||||||
|
return &applyconfigurationsautoscalingv1.ScaleApplyConfiguration{}
|
||||||
|
case autoscalingv1.SchemeGroupVersion.WithKind("ScaleSpec"):
|
||||||
|
return &applyconfigurationsautoscalingv1.ScaleSpecApplyConfiguration{}
|
||||||
|
case autoscalingv1.SchemeGroupVersion.WithKind("ScaleStatus"):
|
||||||
|
return &applyconfigurationsautoscalingv1.ScaleStatusApplyConfiguration{}
|
||||||
|
|
||||||
// Group=autoscaling, Version=v2beta1
|
// Group=autoscaling, Version=v2beta1
|
||||||
case v2beta1.SchemeGroupVersion.WithKind("ContainerResourceMetricSource"):
|
case v2beta1.SchemeGroupVersion.WithKind("ContainerResourceMetricSource"):
|
||||||
|
@ -63,11 +63,12 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
|
|||||||
pkgTypes := packageTypesForInputDirs(context, arguments.InputDirs, arguments.OutputPackagePath)
|
pkgTypes := packageTypesForInputDirs(context, arguments.InputDirs, arguments.OutputPackagePath)
|
||||||
customArgs := arguments.CustomArgs.(*applygenargs.CustomArgs)
|
customArgs := arguments.CustomArgs.(*applygenargs.CustomArgs)
|
||||||
initialTypes := customArgs.ExternalApplyConfigurations
|
initialTypes := customArgs.ExternalApplyConfigurations
|
||||||
refs := refGraphForReachableTypes(pkgTypes, initialTypes)
|
refs := refGraphForReachableTypes(context.Universe, pkgTypes, initialTypes)
|
||||||
typeModels, err := newTypeModels(customArgs.OpenAPISchemaFilePath, pkgTypes)
|
typeModels, err := newTypeModels(customArgs.OpenAPISchemaFilePath, pkgTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Fatalf("Failed build type models from typeModels %s: %v", customArgs.OpenAPISchemaFilePath, err)
|
klog.Fatalf("Failed build type models from typeModels %s: %v", customArgs.OpenAPISchemaFilePath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
groupVersions := make(map[string]clientgentypes.GroupVersions)
|
groupVersions := make(map[string]clientgentypes.GroupVersions)
|
||||||
groupGoNames := make(map[string]string)
|
groupGoNames := make(map[string]string)
|
||||||
applyConfigsForGroupVersion := make(map[clientgentypes.GroupVersion][]applyConfig)
|
applyConfigsForGroupVersion := make(map[clientgentypes.GroupVersion][]applyConfig)
|
||||||
|
@ -28,7 +28,7 @@ type refGraph map[types.Name]string
|
|||||||
|
|
||||||
// refGraphForReachableTypes returns a refGraph that contains all reachable types from
|
// refGraphForReachableTypes returns a refGraph that contains all reachable types from
|
||||||
// the root clientgen types of the provided packages.
|
// the root clientgen types of the provided packages.
|
||||||
func refGraphForReachableTypes(pkgTypes map[string]*types.Package, initialTypes map[types.Name]string) refGraph {
|
func refGraphForReachableTypes(universe types.Universe, pkgTypes map[string]*types.Package, initialTypes map[types.Name]string) refGraph {
|
||||||
var refs refGraph = initialTypes
|
var refs refGraph = initialTypes
|
||||||
|
|
||||||
// Include only types that are reachable from the root clientgen types.
|
// Include only types that are reachable from the root clientgen types.
|
||||||
@ -42,6 +42,20 @@ func refGraphForReachableTypes(pkgTypes map[string]*types.Package, initialTypes
|
|||||||
if tags.GenerateClient && hasApply {
|
if tags.GenerateClient && hasApply {
|
||||||
findReachableTypes(t, reachableTypes)
|
findReachableTypes(t, reachableTypes)
|
||||||
}
|
}
|
||||||
|
// If any apply extensions have custom inputs, add them.
|
||||||
|
for _, extension := range tags.Extensions {
|
||||||
|
if extension.HasVerb("apply") {
|
||||||
|
if len(extension.InputTypeOverride) > 0 {
|
||||||
|
inputType := *t
|
||||||
|
if name, pkg := extension.Input(); len(pkg) > 0 {
|
||||||
|
inputType = *(universe.Type(types.Name{Package: pkg, Name: name}))
|
||||||
|
} else {
|
||||||
|
inputType.Name.Name = extension.InputTypeOverride
|
||||||
|
}
|
||||||
|
findReachableTypes(&inputType, reachableTypes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for pkg, p := range pkgTypes {
|
for pkg, p := range pkgTypes {
|
||||||
|
@ -90,14 +90,20 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
template string
|
template string
|
||||||
args map[string]interface{}
|
args map[string]interface{}
|
||||||
}
|
}
|
||||||
|
_, typeGVString := util.ParsePathGroupVersion(g.inputPackage)
|
||||||
extendedMethods := []extendedInterfaceMethod{}
|
extendedMethods := []extendedInterfaceMethod{}
|
||||||
for _, e := range tags.Extensions {
|
for _, e := range tags.Extensions {
|
||||||
|
if e.HasVerb("apply") && !generateApply {
|
||||||
|
continue
|
||||||
|
}
|
||||||
inputType := *t
|
inputType := *t
|
||||||
resultType := *t
|
resultType := *t
|
||||||
|
inputGVString := typeGVString
|
||||||
// TODO: Extract this to some helper method as this code is copied into
|
// TODO: Extract this to some helper method as this code is copied into
|
||||||
// 2 other places.
|
// 2 other places.
|
||||||
if len(e.InputTypeOverride) > 0 {
|
if len(e.InputTypeOverride) > 0 {
|
||||||
if name, pkg := e.Input(); len(pkg) > 0 {
|
if name, pkg := e.Input(); len(pkg) > 0 {
|
||||||
|
_, inputGVString = util.ParsePathGroupVersion(pkg)
|
||||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||||
inputType = *newType
|
inputType = *newType
|
||||||
} else {
|
} else {
|
||||||
@ -118,7 +124,7 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
} else {
|
} else {
|
||||||
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
|
updatedVerbtemplate = e.VerbName + "(" + strings.TrimPrefix(defaultVerbTemplates[e.VerbType], strings.Title(e.VerbType)+"(")
|
||||||
}
|
}
|
||||||
extendedMethods = append(extendedMethods, extendedInterfaceMethod{
|
extendedMethod := extendedInterfaceMethod{
|
||||||
template: updatedVerbtemplate,
|
template: updatedVerbtemplate,
|
||||||
args: map[string]interface{}{
|
args: map[string]interface{}{
|
||||||
"type": t,
|
"type": t,
|
||||||
@ -128,9 +134,15 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
|
"GetOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "GetOptions"}),
|
||||||
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
|
"ListOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ListOptions"}),
|
||||||
"UpdateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "UpdateOptions"}),
|
"UpdateOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "UpdateOptions"}),
|
||||||
|
"ApplyOptions": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/apis/meta/v1", Name: "ApplyOptions"}),
|
||||||
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
|
"PatchType": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/types", Name: "PatchType"}),
|
||||||
|
"jsonMarshal": c.Universe.Type(types.Name{Package: "encoding/json", Name: "Marshal"}),
|
||||||
},
|
},
|
||||||
})
|
}
|
||||||
|
if e.HasVerb("apply") {
|
||||||
|
extendedMethod.args["inputApplyConfig"] = types.Ref(path.Join(g.applyConfigurationPackage, inputGVString), inputType.Name.Name+"ApplyConfiguration")
|
||||||
|
}
|
||||||
|
extendedMethods = append(extendedMethods, extendedMethod)
|
||||||
}
|
}
|
||||||
m := map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
"type": t,
|
"type": t,
|
||||||
@ -237,14 +249,18 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
if tags.HasVerb("applyStatus") && generateApply {
|
if tags.HasVerb("applyStatus") && generateApply {
|
||||||
sw.Do(applyStatusTemplate, m)
|
sw.Do(applyStatusTemplate, m)
|
||||||
}
|
}
|
||||||
// TODO: Add subresource support once apply subresources are supported on the server side
|
|
||||||
|
|
||||||
// generate expansion methods
|
// generate expansion methods
|
||||||
for _, e := range tags.Extensions {
|
for _, e := range tags.Extensions {
|
||||||
|
if e.HasVerb("apply") && !generateApply {
|
||||||
|
continue
|
||||||
|
}
|
||||||
inputType := *t
|
inputType := *t
|
||||||
resultType := *t
|
resultType := *t
|
||||||
|
inputGVString := typeGVString
|
||||||
if len(e.InputTypeOverride) > 0 {
|
if len(e.InputTypeOverride) > 0 {
|
||||||
if name, pkg := e.Input(); len(pkg) > 0 {
|
if name, pkg := e.Input(); len(pkg) > 0 {
|
||||||
|
_, inputGVString = util.ParsePathGroupVersion(pkg)
|
||||||
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
newType := c.Universe.Type(types.Name{Package: pkg, Name: name})
|
||||||
inputType = *newType
|
inputType = *newType
|
||||||
} else {
|
} else {
|
||||||
@ -262,6 +278,9 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
m["inputType"] = &inputType
|
m["inputType"] = &inputType
|
||||||
m["resultType"] = &resultType
|
m["resultType"] = &resultType
|
||||||
m["subresourcePath"] = e.SubResourcePath
|
m["subresourcePath"] = e.SubResourcePath
|
||||||
|
if e.HasVerb("apply") {
|
||||||
|
m["inputApplyConfig"] = types.Ref(path.Join(g.applyConfigurationPackage, inputGVString), inputType.Name.Name+"ApplyConfiguration")
|
||||||
|
}
|
||||||
|
|
||||||
if e.HasVerb("get") {
|
if e.HasVerb("get") {
|
||||||
if e.IsSubresource() {
|
if e.IsSubresource() {
|
||||||
@ -310,11 +329,14 @@ func (g *genClientForType) GenerateType(c *generator.Context, t *types.Type, w i
|
|||||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m)
|
sw.Do(adjustTemplate(e.VerbName, e.VerbType, patchTemplate), m)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.HasVerb("apply") && generateApply {
|
if e.HasVerb("apply") {
|
||||||
// TODO: Support apply on arbitrary subresource once it is supported by the api-server.
|
if e.IsSubresource() {
|
||||||
|
sw.Do(adjustTemplate(e.VerbName, e.VerbType, applySubresourceTemplate), m)
|
||||||
|
} else {
|
||||||
sw.Do(adjustTemplate(e.VerbName, e.VerbType, applyTemplate), m)
|
sw.Do(adjustTemplate(e.VerbName, e.VerbType, applyTemplate), m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return sw.Error()
|
return sw.Error()
|
||||||
}
|
}
|
||||||
@ -344,7 +366,9 @@ func buildSubresourceDefaultVerbTemplates(generateApply bool) map[string]string
|
|||||||
"update": `Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`,
|
"update": `Update(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputType|raw$, opts $.UpdateOptions|raw$) (*$.resultType|raw$, error)`,
|
||||||
"get": `Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`,
|
"get": `Get(ctx context.Context, $.type|private$Name string, options $.GetOptions|raw$) (*$.resultType|raw$, error)`,
|
||||||
}
|
}
|
||||||
// TODO: Support apply on arbitrary subresource once it is supported by the api-server.
|
if generateApply {
|
||||||
|
m["apply"] = `Apply(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (*$.resultType|raw$, error)`
|
||||||
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,3 +731,30 @@ func (c *$.type|privatePlural$) ApplyStatus(ctx context.Context, $.inputType|pri
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
var applySubresourceTemplate = `
|
||||||
|
// Apply takes top resource name and the apply declarative configuration for $.subresourcePath$,
|
||||||
|
// applies it and returns the applied $.resultType|private$, and an error, if there is any.
|
||||||
|
func (c *$.type|privatePlural$) Apply(ctx context.Context, $.type|private$Name string, $.inputType|private$ *$.inputApplyConfig|raw$, opts $.ApplyOptions|raw$) (result *$.resultType|raw$, err error) {
|
||||||
|
if $.inputType|private$ == nil {
|
||||||
|
return nil, fmt.Errorf("$.inputType|private$ provided to Apply must not be nil")
|
||||||
|
}
|
||||||
|
patchOpts := opts.ToPatchOptions()
|
||||||
|
data, err := $.jsonMarshal|raw$($.inputType|private$)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = &$.resultType|raw${}
|
||||||
|
err = c.client.Patch($.ApplyPatchType|raw$).
|
||||||
|
$if .namespaced$Namespace(c.ns).$end$
|
||||||
|
Resource("$.type|resource$").
|
||||||
|
Name($.type|private$Name).
|
||||||
|
SubResource("$.subresourcePath$").
|
||||||
|
VersionedParams(&patchOpts, $.schemeParameterCodec|raw$).
|
||||||
|
Body(data).
|
||||||
|
Do(ctx).
|
||||||
|
Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
`
|
||||||
|
@ -74,6 +74,7 @@ var unsupportedExtensionVerbs = []string{
|
|||||||
var inputTypeSupportedVerbs = []string{
|
var inputTypeSupportedVerbs = []string{
|
||||||
"create",
|
"create",
|
||||||
"update",
|
"update",
|
||||||
|
"apply",
|
||||||
}
|
}
|
||||||
|
|
||||||
// resultTypeSupportedVerbs is a list of verb types that supports overriding the
|
// resultTypeSupportedVerbs is a list of verb types that supports overriding the
|
||||||
@ -84,6 +85,7 @@ var resultTypeSupportedVerbs = []string{
|
|||||||
"get",
|
"get",
|
||||||
"list",
|
"list",
|
||||||
"patch",
|
"patch",
|
||||||
|
"apply",
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extensions allows to extend the default set of client verbs
|
// Extensions allows to extend the default set of client verbs
|
||||||
|
Loading…
Reference in New Issue
Block a user