Skip to content

Commit 6be5849

Browse files
authored
feat: upgrade the appconfiguration generator framework (#573)
1 parent fa8220c commit 6be5849

File tree

20 files changed

+656
-111
lines changed

20 files changed

+656
-111
lines changed

pkg/cmd/spec/generator_test.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,28 @@ resources:
9494
},
9595
},
9696
}
97+
98+
specModel3 = &models.Spec{
99+
Resources: []models.Resource{
100+
{
101+
ID: "v1:Namespace:default",
102+
Type: "Kubernetes",
103+
Attributes: map[string]interface{}{
104+
"apiVersion": "v1",
105+
"kind": "Namespace",
106+
"spec": make(map[string]interface{}),
107+
"status": make(map[string]interface{}),
108+
"metadata": map[string]interface{}{
109+
"name": "default",
110+
"creationTimestamp": nil,
111+
},
112+
},
113+
Extensions: map[string]interface{}{
114+
"GVK": "/v1, Kind=Namespace",
115+
},
116+
},
117+
},
118+
}
97119
)
98120

99121
func TestGenerateSpecFromFile(t *testing.T) {
@@ -212,7 +234,7 @@ func TestGenerateSpec(t *testing.T) {
212234
Documents: []kclgo.KCLResult{apcMap},
213235
}, nil),
214236
},
215-
want: specModel1,
237+
want: specModel3,
216238
},
217239
}
218240

-2.19 KB
Binary file not shown.

pkg/generator/appconfiguration/generator/accessories/database/database_generator_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ func TestGenerate(t *testing.T) {
150150
"username": database.Username,
151151
},
152152
},
153+
Extensions: map[string]interface{}{
154+
"GVK": "/v1, Kind=Secret",
155+
},
153156
},
154157
},
155158
}

pkg/generator/appconfiguration/generator/app_configurations_generator.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import (
66
"kusionstack.io/kusion/pkg/generator"
77
"kusionstack.io/kusion/pkg/generator/appconfiguration"
88
accessories "kusionstack.io/kusion/pkg/generator/appconfiguration/generator/accessories/database"
9+
"kusionstack.io/kusion/pkg/generator/appconfiguration/generator/monitoring"
910
"kusionstack.io/kusion/pkg/generator/appconfiguration/generator/trait"
1011
"kusionstack.io/kusion/pkg/generator/appconfiguration/generator/workload"
12+
patmonitoring "kusionstack.io/kusion/pkg/generator/appconfiguration/patcher/monitoring"
13+
pattrait "kusionstack.io/kusion/pkg/generator/appconfiguration/patcher/trait"
1114
"kusionstack.io/kusion/pkg/models"
1215
appmodel "kusionstack.io/kusion/pkg/models/appconfiguration"
1316
"kusionstack.io/kusion/pkg/projectstack"
@@ -90,19 +93,28 @@ func (g *appConfigurationGenerator) Generate(spec *models.Spec) error {
9093
spec.Resources = make(models.Resources, 0)
9194
}
9295

96+
// Generate resources
9397
gfs := []appconfiguration.NewGeneratorFunc{
9498
NewNamespaceGeneratorFunc(g.project.Name),
9599
accessories.NewDatabaseGeneratorFunc(g.project, g.stack, g.appName, g.app.Workload, g.app.Database),
96-
workload.NewWorkloadGeneratorFunc(g.project, g.stack, g.appName, g.app.Workload, g.app.Monitoring, g.app.OpsRule),
100+
workload.NewWorkloadGeneratorFunc(g.project, g.stack, g.appName, g.app.Workload),
97101
trait.NewOpsRuleGeneratorFunc(g.project, g.stack, g.appName, g.app),
98-
NewMonitoringGeneratorFunc(g.project, g.app.Monitoring, g.appName),
102+
monitoring.NewMonitoringGeneratorFunc(g.project, g.app.Monitoring, g.appName),
99103
// The OrderedResourcesGenerator should be executed after all resources are generated.
100104
NewOrderedResourcesGeneratorFunc(),
101105
}
102-
103106
if err := appconfiguration.CallGenerators(spec, gfs...); err != nil {
104107
return err
105108
}
106109

110+
// Patcher logic patches generated resources
111+
pfs := []appconfiguration.NewPatcherFunc{
112+
pattrait.NewOpsRulePatcherFunc(g.app),
113+
patmonitoring.NewMonitoringPatcherFunc(g.appName, g.app, g.project),
114+
}
115+
if err := appconfiguration.CallPatchers(spec.Resources.GVKIndex(), pfs...); err != nil {
116+
return err
117+
}
118+
107119
return nil
108120
}

pkg/generator/appconfiguration/generator/monitoring_generator.go renamed to pkg/generator/appconfiguration/generator/monitoring/monitoring_generator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package generator
1+
package monitoring
22

33
import (
44
"fmt"

pkg/generator/appconfiguration/generator/monitoring_generator_test.go renamed to pkg/generator/appconfiguration/generator/monitoring/monitoring_generator_test.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package generator
1+
package monitoring
22

33
import (
44
"fmt"
@@ -82,8 +82,10 @@ func BuildMonitoringTestCase(
8282
},
8383
},
8484
},
85-
DependsOn: nil,
86-
Extensions: nil,
85+
DependsOn: nil,
86+
Extensions: map[string]interface{}{
87+
"GVK": fmt.Sprintf("monitoring.coreos.com/v1, Kind=%s", string(monitorKind)),
88+
},
8789
},
8890
}
8991
}

pkg/generator/appconfiguration/generator/namespace_generator_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,10 @@ func Test_namespaceGenerator_Generate(t *testing.T) {
4545
"spec": make(map[string]interface{}),
4646
"status": make(map[string]interface{}),
4747
},
48-
DependsOn: nil,
49-
Extensions: nil,
48+
DependsOn: nil,
49+
Extensions: map[string]interface{}{
50+
"GVK": "/v1, Kind=Namespace",
51+
},
5052
},
5153
},
5254
},

pkg/generator/appconfiguration/generator/trait/ops_rule_generator_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,11 @@ func Test_opsRuleGenerator_Generate(t *testing.T) {
111111
},
112112
},
113113
}, "status": map[string]interface{}{},
114-
}, DependsOn: []string(nil), Extensions: map[string]interface{}(nil),
114+
},
115+
DependsOn: []string(nil),
116+
Extensions: map[string]interface{}{
117+
"GVK": "apps.kusionstack.io/v1alpha1, Kind=RuleSet",
118+
},
115119
},
116120
},
117121
},

pkg/generator/appconfiguration/generator/workload/secret_generator_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,10 @@ func BuildSecretTestCase(
5858
"immutable": immutable,
5959
"type": string(secretType),
6060
},
61-
DependsOn: nil,
62-
Extensions: nil,
61+
DependsOn: nil,
62+
Extensions: map[string]interface{}{
63+
"GVK": "/v1, Kind=Secret",
64+
},
6365
},
6466
}
6567
testCase := &TestCase{

pkg/generator/appconfiguration/generator/workload/service_generator.go

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,19 @@ import (
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"kusionstack.io/kube-api/apps/v1alpha1"
1010

11-
"k8s.io/apimachinery/pkg/util/intstr"
12-
1311
"kusionstack.io/kusion/pkg/generator/appconfiguration"
1412
"kusionstack.io/kusion/pkg/generator/appconfiguration/generator/workload/network"
1513
"kusionstack.io/kusion/pkg/models"
16-
"kusionstack.io/kusion/pkg/models/appconfiguration/monitoring"
17-
"kusionstack.io/kusion/pkg/models/appconfiguration/trait"
1814
"kusionstack.io/kusion/pkg/models/appconfiguration/workload"
1915
"kusionstack.io/kusion/pkg/projectstack"
2016
)
2117

2218
// workloadServiceGenerator is a struct for generating service workload resources.
2319
type workloadServiceGenerator struct {
24-
project *projectstack.Project
25-
stack *projectstack.Stack
26-
appName string
27-
service *workload.Service
28-
monitoring *monitoring.Monitor
29-
opsRule *trait.OpsRule
20+
project *projectstack.Project
21+
stack *projectstack.Stack
22+
appName string
23+
service *workload.Service
3024
}
3125

3226
// NewWorkloadServiceGenerator returns a new workloadServiceGenerator instance.
@@ -35,8 +29,6 @@ func NewWorkloadServiceGenerator(
3529
stack *projectstack.Stack,
3630
appName string,
3731
service *workload.Service,
38-
monitoring *monitoring.Monitor,
39-
opsRule *trait.OpsRule,
4032
) (appconfiguration.Generator, error) {
4133
if len(project.Name) == 0 {
4234
return nil, fmt.Errorf("project name must not be empty")
@@ -51,12 +43,10 @@ func NewWorkloadServiceGenerator(
5143
}
5244

5345
return &workloadServiceGenerator{
54-
project: project,
55-
stack: stack,
56-
appName: appName,
57-
service: service,
58-
monitoring: monitoring,
59-
opsRule: opsRule,
46+
project: project,
47+
stack: stack,
48+
appName: appName,
49+
service: service,
6050
}, nil
6151
}
6252

@@ -66,11 +56,9 @@ func NewWorkloadServiceGeneratorFunc(
6656
stack *projectstack.Stack,
6757
appName string,
6858
service *workload.Service,
69-
monitoring *monitoring.Monitor,
70-
opsRule *trait.OpsRule,
7159
) appconfiguration.NewGeneratorFunc {
7260
return func() (appconfiguration.Generator, error) {
73-
return NewWorkloadServiceGenerator(project, stack, appName, service, monitoring, opsRule)
61+
return NewWorkloadServiceGenerator(project, stack, appName, service)
7462
}
7563
}
7664

@@ -109,36 +97,8 @@ func (g *workloadServiceGenerator) Generate(spec *models.Spec) error {
10997
}
11098
}
11199

112-
// If Prometheus runs as an operator, it relies on Custom Resources to
113-
// manage the scrape configs. CRs (ServiceMonitors and PodMonitors) rely on
114-
// corresponding resources (Services and Pods) to have labels that can be
115-
// used as part of the label selector for the CR to determine which
116-
// service/pods to scrape from.
117-
// Here we choose the label name kusion_monitoring_appname for two reasons:
118-
// 1. Unlike the label validation in Kubernetes, the label name accepted by
119-
// Prometheus cannot contain non-alphanumeric characters except underscore:
120-
// https://github.com/prometheus/common/blob/main/model/labels.go#L94
121-
// 2. The name should be unique enough that is only created by Kusion and
122-
// used to identify a certain application
123-
monitoringLabels := make(map[string]string)
124-
monitoringAnnotations := make(map[string]string)
125-
if g.monitoring != nil {
126-
if g.project.ProjectConfiguration.Prometheus != nil && g.project.ProjectConfiguration.Prometheus.OperatorMode {
127-
monitoringLabels["kusion_monitoring_appname"] = g.appName
128-
} else if g.project.ProjectConfiguration.Prometheus != nil && !g.project.ProjectConfiguration.Prometheus.OperatorMode {
129-
// If Prometheus doesn't run as an operator, kusion will generate the
130-
// most widely-known annotation for workloads that can be consumed by
131-
// the out-of-the-box community version of Prometheus server
132-
// installation shown as below:
133-
monitoringAnnotations["prometheus.io/scrape"] = "true"
134-
monitoringAnnotations["prometheus.io/scheme"] = g.monitoring.Scheme
135-
monitoringAnnotations["prometheus.io/path"] = g.monitoring.Path
136-
monitoringAnnotations["prometheus.io/port"] = g.monitoring.Port
137-
}
138-
}
139-
140-
labels := appconfiguration.MergeMaps(appconfiguration.UniqueAppLabels(g.project.Name, g.appName), g.service.Labels, monitoringLabels)
141-
annotations := appconfiguration.MergeMaps(g.service.Annotations, monitoringAnnotations)
100+
labels := appconfiguration.MergeMaps(appconfiguration.UniqueAppLabels(g.project.Name, g.appName), g.service.Labels)
101+
annotations := appconfiguration.MergeMaps(g.service.Annotations)
142102
selector := appconfiguration.UniqueAppLabels(g.project.Name, g.appName)
143103

144104
// Create a K8s workload object based on the app's configuration.
@@ -174,15 +134,6 @@ func (g *workloadServiceGenerator) Generate(spec *models.Spec) error {
174134
Selector: &metav1.LabelSelector{MatchLabels: selector},
175135
Template: podTemplateSpec,
176136
}
177-
if g.opsRule != nil && g.opsRule.MaxUnavailable != "" {
178-
maxUnavailable := intstr.Parse(g.opsRule.MaxUnavailable)
179-
spec.Strategy = appsv1.DeploymentStrategy{
180-
Type: appsv1.RollingUpdateDeploymentStrategyType,
181-
RollingUpdate: &appsv1.RollingUpdateDeployment{
182-
MaxUnavailable: &maxUnavailable,
183-
},
184-
}
185-
}
186137
resource = &appsv1.Deployment{
187138
TypeMeta: typeMeta,
188139
ObjectMeta: objectMeta,

0 commit comments

Comments
 (0)