Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v1.15] Lazily initialize assets #2236

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions assets/monitoring/grafana/v1alpha1/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,54 +7,75 @@ import (
"github.com/scylladb/scylla-operator/pkg/assets"
"github.com/scylladb/scylla-operator/pkg/helpers"
"github.com/scylladb/scylla-operator/pkg/scheme"
"github.com/scylladb/scylla-operator/pkg/util/lazy"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) assets.ObjectTemplate[T] {
func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) *assets.ObjectTemplate[T] {
return assets.ParseObjectTemplateOrDie[T](name, tmplString, assets.TemplateFuncs, scheme.Codecs.UniversalDeserializer())
}

var (
//go:embed "deployment.yaml"
grafanaDeploymentTemplateString string
GrafanaDeploymentTemplate = ParseObjectTemplateOrDie[*appsv1.Deployment]("grafana-deployment", grafanaDeploymentTemplateString)
GrafanaDeploymentTemplate = lazy.New(func() *assets.ObjectTemplate[*appsv1.Deployment] {
return ParseObjectTemplateOrDie[*appsv1.Deployment]("grafana-deployment", grafanaDeploymentTemplateString)
})

//go:embed "serviceaccount.yaml"
grafanaSATemplateString string
GrafanaSATemplate = ParseObjectTemplateOrDie[*corev1.ServiceAccount]("grafana-sa", grafanaSATemplateString)
GrafanaSATemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ServiceAccount] {
return ParseObjectTemplateOrDie[*corev1.ServiceAccount]("grafana-sa", grafanaSATemplateString)
})

//go:embed "configs.cm.yaml"
grafanaConfigsTemplateString string
GrafanaConfigsTemplate = ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-configs-cm", grafanaConfigsTemplateString)
GrafanaConfigsTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ConfigMap] {
return ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-configs-cm", grafanaConfigsTemplateString)
})

//go:embed "admin-credentials.secret.yaml"
grafanaAdminCredentialsSecretTemplateString string
GrafanaAdminCredentialsSecretTemplate = ParseObjectTemplateOrDie[*corev1.Secret]("grafana-access-credentials-secret", grafanaAdminCredentialsSecretTemplateString)
GrafanaAdminCredentialsSecretTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.Secret] {
return ParseObjectTemplateOrDie[*corev1.Secret]("grafana-access-credentials-secret", grafanaAdminCredentialsSecretTemplateString)
})

//go:embed "provisioning.cm.yaml"
grafanaProvisioningConfigMapTemplateString string
GrafanaProvisioningConfigMapTemplate = ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-provisioning-cm", grafanaProvisioningConfigMapTemplateString)
GrafanaProvisioningConfigMapTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ConfigMap] {
return ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-provisioning-cm", grafanaProvisioningConfigMapTemplateString)
})

//go:embed "dashboards.cm.yaml"
grafanaDashboardsConfigMapTemplateString string
GrafanaDashboardsConfigMapTemplate = ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-dashboards-cm", grafanaDashboardsConfigMapTemplateString)
GrafanaDashboardsConfigMapTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ConfigMap] {
return ParseObjectTemplateOrDie[*corev1.ConfigMap]("grafana-dashboards-cm", grafanaDashboardsConfigMapTemplateString)
})

//go:embed "dashboards/platform/*/*.json"
grafanaDashboardsPlatformFS embed.FS
GrafanaDashboardsPlatform = helpers.Must(NewGrafanaDashboardsFromFS(grafanaDashboardsPlatformFS, "dashboards/platform"))
GrafanaDashboardsPlatform = lazy.New(func() GrafanaDashboardsFoldersMap {
return helpers.Must(NewGrafanaDashboardsFromFS(grafanaDashboardsPlatformFS, "dashboards/platform"))
})

//go:embed "dashboards/saas/*/*.json"
grafanaDashboardsSAASFS embed.FS
GrafanaDashboardsSAAS = helpers.Must(NewGrafanaDashboardsFromFS(grafanaDashboardsSAASFS, "dashboards/saas"))
GrafanaDashboardsSAAS = lazy.New(func() GrafanaDashboardsFoldersMap {
return helpers.Must(NewGrafanaDashboardsFromFS(grafanaDashboardsSAASFS, "dashboards/saas"))
})

//go:embed "service.yaml"
grafanaServiceTemplateString string
GrafanaServiceTemplate = ParseObjectTemplateOrDie[*corev1.Service]("grafana-service", grafanaServiceTemplateString)
GrafanaServiceTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.Service] {
return ParseObjectTemplateOrDie[*corev1.Service]("grafana-service", grafanaServiceTemplateString)
})

//go:embed "ingress.yaml"
grafanaIngressTemplateString string
GrafanaIngressTemplate = ParseObjectTemplateOrDie[*networkingv1.Ingress]("grafana-ingress", grafanaIngressTemplateString)
GrafanaIngressTemplate = lazy.New(func() *assets.ObjectTemplate[*networkingv1.Ingress] {
return ParseObjectTemplateOrDie[*networkingv1.Ingress]("grafana-ingress", grafanaIngressTemplateString)
})
)
43 changes: 32 additions & 11 deletions assets/monitoring/prometheus/v1/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,75 @@ import (
monitoringv1 "github.com/scylladb/scylla-operator/pkg/externalapi/monitoring/v1"
"github.com/scylladb/scylla-operator/pkg/helpers"
"github.com/scylladb/scylla-operator/pkg/scheme"
"github.com/scylladb/scylla-operator/pkg/util/lazy"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) assets.ObjectTemplate[T] {
func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) *assets.ObjectTemplate[T] {
return assets.ParseObjectTemplateOrDie[T](name, tmplString, assets.TemplateFuncs, scheme.Codecs.UniversalDeserializer())
}

var (
//go:embed "prometheus.yaml"
prometheusTemplateString string
PrometheusTemplate = ParseObjectTemplateOrDie[*monitoringv1.Prometheus]("prometheus", prometheusTemplateString)
PrometheusTemplate = lazy.New(func() *assets.ObjectTemplate[*monitoringv1.Prometheus] {
return ParseObjectTemplateOrDie[*monitoringv1.Prometheus]("prometheus", prometheusTemplateString)
})

//go:embed "serviceaccount.yaml"
prometheusSATemplateString string
PrometheusSATemplate = ParseObjectTemplateOrDie[*corev1.ServiceAccount]("prometheus-sa", prometheusSATemplateString)
PrometheusSATemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ServiceAccount] {
return ParseObjectTemplateOrDie[*corev1.ServiceAccount]("prometheus-sa", prometheusSATemplateString)
})

//go:embed "rolebinding.yaml"
prometheusRoleBindingTemplateString string
PrometheusRoleBindingTemplate = ParseObjectTemplateOrDie[*rbacv1.RoleBinding]("prometheus-rolebinding", prometheusRoleBindingTemplateString)
PrometheusRoleBindingTemplate = lazy.New(func() *assets.ObjectTemplate[*rbacv1.RoleBinding] {
return ParseObjectTemplateOrDie[*rbacv1.RoleBinding]("prometheus-rolebinding", prometheusRoleBindingTemplateString)
})

//go:embed "service.yaml"
prometheusServiceTemplateString string
PrometheusServiceTemplate = ParseObjectTemplateOrDie[*corev1.Service]("prometheus-service", prometheusServiceTemplateString)
PrometheusServiceTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.Service] {
return ParseObjectTemplateOrDie[*corev1.Service]("prometheus-service", prometheusServiceTemplateString)
})

//go:embed "scylladb.servicemonitor.yaml"
scyllaDBServiceMonitorTemplateString string
ScyllaDBServiceMonitorTemplate = ParseObjectTemplateOrDie[*monitoringv1.ServiceMonitor]("scylladb-servicemonitor", scyllaDBServiceMonitorTemplateString)
ScyllaDBServiceMonitorTemplate = lazy.New(func() *assets.ObjectTemplate[*monitoringv1.ServiceMonitor] {
return ParseObjectTemplateOrDie[*monitoringv1.ServiceMonitor]("scylladb-servicemonitor", scyllaDBServiceMonitorTemplateString)
})

//go:embed "rules/**"
prometheusRulesFS embed.FS
PrometheusRules = helpers.Must(NewPrometheusRulesFromFS(prometheusRulesFS))
PrometheusRules = lazy.New(func() PrometheusRulesMap {
return helpers.Must(NewPrometheusRulesFromFS(prometheusRulesFS))
})

//go:embed "latency.prometheusrule.yaml"
latencyPrometheusRuleTemplateString string
LatencyPrometheusRuleTemplate = ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("latency-prometheus-rule", latencyPrometheusRuleTemplateString)
LatencyPrometheusRuleTemplate = lazy.New(func() *assets.ObjectTemplate[*monitoringv1.PrometheusRule] {
return ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("latency-prometheus-rule", latencyPrometheusRuleTemplateString)
})

//go:embed "alerts.prometheusrule.yaml"
alertsPrometheusRuleTemplateString string
AlertsPrometheusRuleTemplate = ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("alerts-prometheus-rule", alertsPrometheusRuleTemplateString)
AlertsPrometheusRuleTemplate = lazy.New(func() *assets.ObjectTemplate[*monitoringv1.PrometheusRule] {
return ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("alerts-prometheus-rule", alertsPrometheusRuleTemplateString)
})

//go:embed "table.prometheusrule.yaml"
tablePrometheusRuleTemplateString string
TablePrometheusRuleTemplate = ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("table-prometheus-rule", tablePrometheusRuleTemplateString)
TablePrometheusRuleTemplate = lazy.New(func() *assets.ObjectTemplate[*monitoringv1.PrometheusRule] {
return ParseObjectTemplateOrDie[*monitoringv1.PrometheusRule]("table-prometheus-rule", tablePrometheusRuleTemplateString)
})

//go:embed "ingress.yaml"
prometheusIngressTemplateString string
PrometheusIngressTemplate = ParseObjectTemplateOrDie[*networkingv1.Ingress]("prometheus-ingress", prometheusIngressTemplateString)
PrometheusIngressTemplate = lazy.New(func() *assets.ObjectTemplate[*networkingv1.Ingress] {
return ParseObjectTemplateOrDie[*networkingv1.Ingress]("prometheus-ingress", prometheusIngressTemplateString)
})
)
7 changes: 5 additions & 2 deletions assets/scylladb/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ import (

"github.com/scylladb/scylla-operator/pkg/assets"
"github.com/scylladb/scylla-operator/pkg/scheme"
"github.com/scylladb/scylla-operator/pkg/util/lazy"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) assets.ObjectTemplate[T] {
func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string) *assets.ObjectTemplate[T] {
return assets.ParseObjectTemplateOrDie[T](name, tmplString, assets.TemplateFuncs, scheme.Codecs.UniversalDeserializer())
}

var (
//go:embed "managedconfig.cm.yaml"
scyllaDBManagedConfigTemplateString string
ScyllaDBManagedConfigTemplate = ParseObjectTemplateOrDie[*corev1.ConfigMap]("scylladb-managed-config", scyllaDBManagedConfigTemplateString)
ScyllaDBManagedConfigTemplate = lazy.New(func() *assets.ObjectTemplate[*corev1.ConfigMap] {
return ParseObjectTemplateOrDie[*corev1.ConfigMap]("scylladb-managed-config", scyllaDBManagedConfigTemplateString)
})
)
8 changes: 4 additions & 4 deletions pkg/assets/object_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ type ObjectTemplate[T runtime.Object] struct {
decoder runtime.Decoder
}

func ParseObjectTemplate[T runtime.Object](name, tmplString string, funcMap template.FuncMap, decoder runtime.Decoder) (ObjectTemplate[T], error) {
func ParseObjectTemplate[T runtime.Object](name, tmplString string, funcMap template.FuncMap, decoder runtime.Decoder) (*ObjectTemplate[T], error) {
tmpl, err := template.New(name).Funcs(funcMap).Parse(tmplString)
if err != nil {
return *new(ObjectTemplate[T]), fmt.Errorf("can't parse template %q: %w", name, err)
return new(ObjectTemplate[T]), fmt.Errorf("can't parse template %q: %w", name, err)
}

return ObjectTemplate[T]{
return &ObjectTemplate[T]{
tmpl: tmpl,
decoder: decoder,
}, nil
}

func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string, funcMap template.FuncMap, decoder runtime.Decoder) ObjectTemplate[T] {
func ParseObjectTemplateOrDie[T runtime.Object](name, tmplString string, funcMap template.FuncMap, decoder runtime.Decoder) *ObjectTemplate[T] {
return helpers.Must(ParseObjectTemplate[T](name, tmplString, funcMap, decoder))
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/scylladbdatacenter/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -1720,7 +1720,7 @@ func MakeManagedScyllaDBConfig(sdc *scyllav1alpha1.ScyllaDBDatacenter) (*corev1.
return pointer.Ptr(false)
}

cm, _, err := scylladbassets.ScyllaDBManagedConfigTemplate.RenderObject(
cm, _, err := scylladbassets.ScyllaDBManagedConfigTemplate.Get().RenderObject(
map[string]any{
"Namespace": sdc.Namespace,
"Name": naming.GetScyllaDBManagedConfigCMName(sdc.Name),
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/scylladbmonitoring/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestMain(m *testing.M) {
// We need to make sure that all prometheus rules (coming from scylladb monitoring) are wired.
// Note that this can also mean we just lack coverage but both cases should be fixed.
var errs []error
for f, r := range prometheusv1assets.PrometheusRules {
for f, r := range prometheusv1assets.PrometheusRules.Get() {
if !r.Accessed() {
errs = append(errs, fmt.Errorf("prometheus rule %q has not been used in any test and may not be used in the codebase", f))
}
Expand Down
20 changes: 10 additions & 10 deletions pkg/controller/scylladbmonitoring/sync_grafana.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func makeGrafanaDeployment(sm *scyllav1alpha1.ScyllaDBMonitoring, soc *scyllav1a
return nil, "", fmt.Errorf("dashboardsCMs can't be empty")
}

return grafanav1alpha1assets.GrafanaDeploymentTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaDeploymentTemplate.Get().RenderObject(map[string]any{
"grafanaImage": grafanaImage,
"bashToolsImage": bashToolsImage,
"scyllaDBMonitoringName": sm.Name,
Expand All @@ -135,14 +135,14 @@ func makeGrafanaAdminCredentials(sm *scyllav1alpha1.ScyllaDBMonitoring, secrets
existingPassword = []byte(rand.String(grafanaPasswordLength))
}

return grafanav1alpha1assets.GrafanaAdminCredentialsSecretTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaAdminCredentialsSecretTemplate.Get().RenderObject(map[string]any{
"name": secretName,
"password": existingPassword,
})
}

func makeGrafanaSA(sm *scyllav1alpha1.ScyllaDBMonitoring) (*corev1.ServiceAccount, string, error) {
return grafanav1alpha1assets.GrafanaSATemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaSATemplate.Get().RenderObject(map[string]any{
"namespace": sm.Namespace,
"scyllaDBMonitoringName": sm.Name,
})
Expand All @@ -165,7 +165,7 @@ func makeGrafanaConfigs(sm *scyllav1alpha1.ScyllaDBMonitoring) (*corev1.ConfigMa
return nil, "", fmt.Errorf("unkown monitoring type: %q", t)
}

return grafanav1alpha1assets.GrafanaConfigsTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaConfigsTemplate.Get().RenderObject(map[string]any{
"scyllaDBMonitoringName": sm.Name,
"enableAnonymousAccess": enableAnonymousAccess,
"defaultDashboard": defaultDashboard,
Expand All @@ -176,16 +176,16 @@ func makeGrafanaDashboards(sm *scyllav1alpha1.ScyllaDBMonitoring) ([]*corev1.Con
var dashboardsFoldersMap grafanav1alpha1assets.GrafanaDashboardsFoldersMap
switch t := sm.Spec.GetType(); t {
case scyllav1alpha1.ScyllaDBMonitoringTypePlatform:
dashboardsFoldersMap = grafanav1alpha1assets.GrafanaDashboardsPlatform
dashboardsFoldersMap = grafanav1alpha1assets.GrafanaDashboardsPlatform.Get()
case scyllav1alpha1.ScyllaDBMonitoringTypeSAAS:
dashboardsFoldersMap = grafanav1alpha1assets.GrafanaDashboardsSAAS
dashboardsFoldersMap = grafanav1alpha1assets.GrafanaDashboardsSAAS.Get()
default:
return nil, fmt.Errorf("unkown monitoring type: %q", t)
}

var cms []*corev1.ConfigMap
for name, folder := range dashboardsFoldersMap {
cm, _, err := grafanav1alpha1assets.GrafanaDashboardsConfigMapTemplate.RenderObject(map[string]any{
cm, _, err := grafanav1alpha1assets.GrafanaDashboardsConfigMapTemplate.Get().RenderObject(map[string]any{
"scyllaDBMonitoringName": sm.Name,
"dashboardsName": name,
"dashboards": folder,
Expand All @@ -205,13 +205,13 @@ func makeGrafanaDashboards(sm *scyllav1alpha1.ScyllaDBMonitoring) ([]*corev1.Con
}

func makeGrafanaProvisionings(sm *scyllav1alpha1.ScyllaDBMonitoring) (*corev1.ConfigMap, string, error) {
return grafanav1alpha1assets.GrafanaProvisioningConfigMapTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaProvisioningConfigMapTemplate.Get().RenderObject(map[string]any{
"scyllaDBMonitoringName": sm.Name,
})
}

func makeGrafanaService(sm *scyllav1alpha1.ScyllaDBMonitoring) (*corev1.Service, string, error) {
return grafanav1alpha1assets.GrafanaServiceTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaServiceTemplate.Get().RenderObject(map[string]any{
"scyllaDBMonitoringName": sm.Name,
})
}
Expand All @@ -230,7 +230,7 @@ func makeGrafanaIngress(sm *scyllav1alpha1.ScyllaDBMonitoring) (*networkingv1.In
return nil, "", nil
}

return grafanav1alpha1assets.GrafanaIngressTemplate.RenderObject(map[string]any{
return grafanav1alpha1assets.GrafanaIngressTemplate.Get().RenderObject(map[string]any{
"scyllaDBMonitoringName": sm.Name,
"dnsDomains": ingressOptions.DNSDomains,
"ingressAnnotations": ingressOptions.Annotations,
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/scylladbmonitoring/sync_grafana_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func Test_makeGrafanaDashboards(t *testing.T) {
t.Helper()

var expectedPlatformConfigMaps []*corev1.ConfigMap
for dashboardFolderName, dashboardFolder := range grafanav1alpha1assets.GrafanaDashboardsPlatform {
for dashboardFolderName, dashboardFolder := range grafanav1alpha1assets.GrafanaDashboardsPlatform.Get() {
cm := &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
Expand Down
Loading