Skip to content

Commit 53cda40

Browse files
committed
add partial rendering
1 parent 76d27d1 commit 53cda40

File tree

7 files changed

+137
-71
lines changed

7 files changed

+137
-71
lines changed

acceptance/features/console-upgrades.feature

Whitespace-only changes.

charts/console/rendervalues.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ type RenderValues struct {
5555
SecretMounts []SecretMount `json:"secretMounts"`
5656
Secret SecretConfig `json:"secret"`
5757
LicenseSecretRef *corev1.SecretKeySelector `json:"licenseSecretRef,omitempty"`
58-
LivenessProbe corev1.Probe `json:"livenessProbe"`
59-
ReadinessProbe corev1.Probe `json:"readinessProbe"`
58+
LivenessProbe corev1.Probe `json:"livenessProbe" partial:"builtin"`
59+
ReadinessProbe corev1.Probe `json:"readinessProbe" partial:"builtin"`
6060
ConfigMap Creatable `json:"configmap"`
6161
Deployment DeploymentConfig `json:"deployment"`
6262
Strategy appsv1.DeploymentStrategy `json:"strategy"`

charts/console/rendervalues_partial.gen.go

Lines changed: 39 additions & 38 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gen/partial/partial.go

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ const (
4545
mode = packages.NeedTypes | packages.NeedName | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedImports
4646
)
4747

48+
type partialImport struct {
49+
Name string
50+
Path string
51+
}
52+
53+
var packagePartials = map[string]partialImport{
54+
"k8s.io/api/core/v1": {
55+
Name: "applycorev1",
56+
Path: "k8s.io/client-go/applyconfigurations/core/v1",
57+
},
58+
}
59+
4860
func Cmd() *cobra.Command {
4961
var outFlag string
5062
var headerFlag string
@@ -127,7 +139,7 @@ func (g *Generator) Generate(t types.Type) []ast.Node {
127139
// reference needs to be a pointer or changed to a newly generated
128140
// type. Partialization of (anonymous) structs, is generation of a new
129141
// struct type.
130-
partialized := g.partialize(named.Underlying())
142+
partialized := g.partialize(named.Underlying(), nil)
131143

132144
var params *ast.FieldList
133145
if named.TypeParams().Len() > 0 {
@@ -185,22 +197,22 @@ func (g *Generator) typeToNode(t types.Type) ast.Node {
185197
return node
186198
}
187199

188-
func (g *Generator) partialize(t types.Type) types.Type {
200+
func (g *Generator) partialize(t types.Type, tag *StructTag) types.Type {
189201
// TODO cache me.
190202

191203
switch t := t.(type) {
192204
case *types.Basic, *types.Interface, *types.Alias:
193205
return t
194206
case *types.Pointer:
195-
return types.NewPointer(g.partialize(t.Elem()))
207+
return types.NewPointer(g.partialize(t.Elem(), tag))
196208
case *types.Map:
197-
return types.NewMap(t.Key(), g.partialize(t.Elem()))
209+
return types.NewMap(t.Key(), g.partialize(t.Elem(), nil))
198210
case *types.Slice:
199-
return types.NewSlice(g.partialize(t.Elem()))
211+
return types.NewSlice(g.partialize(t.Elem(), tag))
200212
case *types.Struct:
201213
return g.partializeStruct(t)
202214
case *types.Named:
203-
return g.partializeNamed(t)
215+
return g.partializeNamed(t, tag)
204216
case *types.TypeParam:
205217
return t // TODO this isn't super easy to fully support without a lot of additional information......
206218
default:
@@ -214,7 +226,7 @@ func (g *Generator) partializeStruct(t *types.Struct) *types.Struct {
214226
for i := 0; i < t.NumFields(); i++ {
215227
field := t.Field(i)
216228

217-
partialized := g.partialize(field.Type())
229+
partialized := g.partialize(field.Type(), parseTag(t.Tag(i)).Named("partial"))
218230
switch partialized.Underlying().(type) {
219231
case *types.Basic:
220232
partialized = types.NewPointer(partialized)
@@ -240,7 +252,7 @@ func (g *Generator) partializeStruct(t *types.Struct) *types.Struct {
240252
return types.NewStruct(fields, tags)
241253
}
242254

243-
func (g *Generator) partializeNamed(t *types.Named) types.Type {
255+
func (g *Generator) partializeNamed(t *types.Named, tag *StructTag) types.Type {
244256
// If there exists a Partial___ variant of the type, we'll use this. This
245257
// allows Partial structs to references partial structs from other packages
246258
// that contain Partialized structs and/or allows end users to provide
@@ -266,6 +278,38 @@ func (g *Generator) partializeNamed(t *types.Named) types.Type {
266278
// NB: This check MUST match the check in FindAllNames.
267279
isPartialized := inPkg && !IsType[*types.Basic](t.Underlying())
268280
if !isPartialized {
281+
if tag != nil {
282+
for _, value := range tag.Values {
283+
if value == "builtin" {
284+
path := t.Obj().Pkg().Path()
285+
if override, ok := packagePartials[path]; ok {
286+
var args []types.Type
287+
for i := 0; i < t.TypeArgs().Len(); i++ {
288+
args = append(args, g.partialize(t.TypeArgs().At(i), nil))
289+
}
290+
291+
params := make([]*types.TypeParam, t.TypeParams().Len())
292+
for i := 0; i < t.TypeParams().Len(); i++ {
293+
param := t.TypeParams().At(i)
294+
// Might need to clone the typename here
295+
params[i] = types.NewTypeParam(param.Obj(), param.Constraint())
296+
}
297+
298+
named := types.NewNamed(types.NewTypeName(0, types.NewPackage(override.Path, override.Name), t.Obj().Name()+"ApplyConfiguration", t.Underlying()), t.Underlying(), nil)
299+
if len(args) < 1 {
300+
return named
301+
}
302+
named.SetTypeParams(params)
303+
result, err := types.Instantiate(nil, named, args, true)
304+
if err != nil {
305+
panic(err)
306+
}
307+
return result
308+
}
309+
}
310+
}
311+
}
312+
269313
// If we haven't partialized this type, there's nothing we can do. Noop.
270314
return t
271315
}
@@ -277,7 +321,7 @@ func (g *Generator) partializeNamed(t *types.Named) types.Type {
277321

278322
var args []types.Type
279323
for i := 0; i < t.TypeArgs().Len(); i++ {
280-
args = append(args, g.partialize(t.TypeArgs().At(i)))
324+
args = append(args, g.partialize(t.TypeArgs().At(i), nil))
281325
}
282326

283327
params := make([]*types.TypeParam, t.TypeParams().Len())
@@ -369,6 +413,14 @@ func GeneratePartial(pkg *packages.Package, structName string, outPackage string
369413
if pkg, ok := originalImports[parent.Name]; ok {
370414
imports[parent.Name] = pkg
371415
}
416+
417+
for _, pkg := range packagePartials {
418+
if pkg.Name == parent.Name {
419+
// NB: we don't actually use the import name below, so
420+
// we just set it to empty here
421+
imports[pkg.Name] = types.NewPackage(pkg.Path, "")
422+
}
423+
}
372424
}
373425
return true
374426
})
@@ -524,6 +576,9 @@ func EnsureOmitEmpty(tag string) string {
524576

525577
var out strings.Builder
526578
for i, p := range parts {
579+
if p.Name == "partial" {
580+
continue
581+
}
527582
if i > 0 {
528583
_, _ = out.WriteRune(' ')
529584
}
@@ -547,7 +602,18 @@ func IsType[T types.Type](typ types.Type) bool {
547602

548603
var tagRe = regexp.MustCompile(`([a-z_]+):"([^"]+)"`)
549604

550-
func parseTag(tag string) []StructTag {
605+
type StructTags []StructTag
606+
607+
func (t StructTags) Named(name string) *StructTag {
608+
for i, tag := range t {
609+
if tag.Name == name {
610+
return &t[i]
611+
}
612+
}
613+
return nil
614+
}
615+
616+
func parseTag(tag string) StructTags {
551617
matches := tagRe.FindAllStringSubmatch(tag, -1)
552618

553619
tags := make([]StructTag, len(matches))

go.work.sum

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ buf.build/gen/go/redpandadata/common/connectrpc/go v1.16.2-20240508150812-e0d0fb
2323
buf.build/gen/go/redpandadata/common/connectrpc/go v1.18.1-20240917150400-3f349e63f44a.1 h1:EPRfGAJDTnM3J3MPGMPEs+HBezpiE/8lTWB3kdlQTGI=
2424
buf.build/gen/go/redpandadata/common/connectrpc/go v1.18.1-20240917150400-3f349e63f44a.1/go.mod h1:ZNgPT3k1W0p+EkMibCzOqoHOhNDi1ym6RH7/kGEHeKE=
2525
buf.build/gen/go/redpandadata/common/protocolbuffers/go v1.34.2-20240715174743-9c0afe867874.2/go.mod h1:wThyg02xJx4K/DA5fg0QlKts8XVPyTT86JC8hPfEzno=
26+
buf.build/gen/go/redpandadata/core/connectrpc/go v1.19.1-20251031193904-15e1d027dabd.2 h1:jCG4Odp8EuikMWru6WwVylzjrSfJImAfrNeImtfp6rs=
27+
buf.build/gen/go/redpandadata/core/connectrpc/go v1.19.1-20251031193904-15e1d027dabd.2/go.mod h1:YY+peV2t5WRrsN5JCawfDfdePKQVNhaO+0l/9Tsi+oY=
28+
buf.build/gen/go/redpandadata/core/protocolbuffers/go v1.36.10-20251031193904-15e1d027dabd.1 h1:qbwdlxQSRcBFlq8Kcl532kcMuR+64TuvnhLC49FxzJE=
29+
buf.build/gen/go/redpandadata/core/protocolbuffers/go v1.36.10-20251031193904-15e1d027dabd.1/go.mod h1:QenSPzqxZpyo9hHIpRzTetvDchelVDzimnmaggHKenc=
2630
buf.build/gen/go/redpandadata/dataplane/connectrpc/go v1.16.2-20240620104934-3415ce922cfb.1/go.mod h1:R0DNyd3sxZqaTQrcjSgGaJqHndFCf3kKHBbXgKYzKDY=
2731
buf.build/gen/go/redpandadata/dataplane/protocolbuffers/go v1.34.2-20240620104934-3415ce922cfb.2/go.mod h1:AcLjVYZHtwlZvBrjuqyjtZtHv9BbDaHD6C92lO/gJFI=
2832
buf.build/gen/go/redpandadata/dataplane/protocolbuffers/go v1.36.2-20250404200318-65f29ddd7b29.1/go.mod h1:zTNjffbkXs9K5/sbSlagide7l0hSTs+Oa1j39yENO8M=
@@ -694,6 +698,8 @@ cloud.google.com/go/workflows v1.14.0/go.mod h1:kjar2tf4qQu7VoCTFX+L3yy+2dIFTWr6
694698
cloud.google.com/go/workflows v1.14.2 h1:phBz5TOAES0YGogxZ6Q7ISSudaf618lRhE3euzBpE9U=
695699
cloud.google.com/go/workflows v1.14.2/go.mod h1:5nqKjMD+MsJs41sJhdVrETgvD5cOK3hUcAs8ygqYvXQ=
696700
connectrpc.com/connect v1.16.2/go.mod h1:n2kgwskMHXC+lVqb18wngEpF95ldBHXjZYJussz5FRc=
701+
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
702+
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
697703
connectrpc.com/grpcreflect v1.2.0 h1:Q6og1S7HinmtbEuBvARLNwYmTbhEGRpHDhqrPNlmK+U=
698704
connectrpc.com/grpcreflect v1.2.0/go.mod h1:nwSOKmE8nU5u/CidgHtPYk1PFI3U9ignz7iDMxOYkSY=
699705
connectrpc.com/grpcreflect v1.3.0 h1:Y4V+ACf8/vOb1XOc251Qun7jMB75gCUNw6llvB9csXc=
@@ -1416,6 +1422,8 @@ github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
14161422
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
14171423
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
14181424
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM=
1425+
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
1426+
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
14191427
github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA=
14201428
github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
14211429
github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
@@ -3198,6 +3206,8 @@ google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojt
31983206
google.golang.org/protobuf v1.36.4/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
31993207
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
32003208
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
3209+
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
3210+
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
32013211
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
32023212
gopkg.in/alecthomas/kingpin.v1 v1.3.7/go.mod h1:vs0oy7ub8knYaut5kITUTmx/WeE4xRuEeOR34yEAWEA=
32033213
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=

operator/api/redpanda/v1alpha2/conversion.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
appsv1 "k8s.io/api/apps/v1"
1717
corev1 "k8s.io/api/core/v1"
1818
"k8s.io/apimachinery/pkg/runtime"
19+
applycorev1 "k8s.io/client-go/applyconfigurations/core/v1"
1920

2021
"github.com/redpanda-data/redpanda-operator/charts/console/v3"
2122
"github.com/redpanda-data/redpanda-operator/pkg/ir"
@@ -299,12 +300,11 @@ var (
299300
conv_runtime_RawExtension_To_corev1_Volume = convertRuntimeRawExtension[corev1.Volume]
300301
conv_runtime_RawExtension_To_corev1_VolumeMount = convertRuntimeRawExtension[corev1.VolumeMount]
301302

302-
// TODO THIS IS BAD AND BROKEN (Will write 0s for unspecified fields and generate invalid options).
303-
// ConsolePartialValues really needs to have ApplyConfigs for most k8s types.
304-
// Upgrade gen partial to pull an overridden type from a comment or field tag?
305-
conv_LivenessProbe_To_ProbeApplyConfiguration = convertViaMarshaling[*LivenessProbe, *ProbeApplyConfiguration]
306-
conv_ProbeApplyConfiguration_To_corev1_Probe = convertViaMarshaling[ProbeApplyConfiguration, corev1.Probe]
307-
conv_ReadinessProbe_To_ProbeApplyConfiguration = convertViaMarshaling[*ReadinessProbe, *ProbeApplyConfiguration]
303+
// LivenessProbe/ReadinessProbe conversions (RedpandaConsole -> Console)
304+
305+
conv_LivenessProbe_To_ProbeApplyConfiguration = convertViaMarshaling[*LivenessProbe, *ProbeApplyConfiguration]
306+
conv_ReadinessProbe_To_ProbeApplyConfiguration = convertViaMarshaling[*ReadinessProbe, *ProbeApplyConfiguration]
307+
conv_ProbeApplyConfiguration_To_ProbeApplyConfiguration = convertViaMarshaling[*ProbeApplyConfiguration, *applycorev1.ProbeApplyConfiguration]
308308
)
309309

310310
type deepCopier[T any] interface {

0 commit comments

Comments
 (0)