Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Feature request: adding an object as a value #77

Open
siredmar opened this issue Nov 16, 2022 · 0 comments
Open

Feature request: adding an object as a value #77

siredmar opened this issue Nov 16, 2022 · 0 comments

Comments

@siredmar
Copy link

This is really a great project!
However i'm missing a feature: It would be really nice, if i could embedd whole objects as values.

I created a generic CRD that uses a json.RawMessage in my Spec (see details for spec) to take all kinds of values no matter what the struct is. This way i can template whatever i want.

/*
Copyright 2022.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
	"encoding/json"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// EDIT THIS FILE!  THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required.  Any new fields you add must have json tags for the fields to be serialized.

// MyCRDOverriderSpec defines the desired state of MyCRDOverrider
type MyCRDOverriderSpec struct {
	// Foo is an example field of MyCRDOverrider. Edit MyCRDoverrider_types.go to remove/update
	// +kubebuilder:validation:Schemaless
	// +kubebuilder:pruning:PreserveUnknownFields
	// +kubebuilder:validation:Type=object
	Values json.RawMessage `json:"values"`
}

// MyCRDOverriderStatus defines the observed state of MyCRDOverrider
type MyCRDOverriderStatus struct {
	// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
	// Important: Run "make" to regenerate code after modifying this file
}

//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// MyCRDOverrider is the Schema for the MyCRDoverriders API
type MyCRDOverrider struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   MyCRDOverriderSpec   `json:"spec,omitempty"`
	Status MyCRDOverriderStatus `json:"status,omitempty"`
}

//+kubebuilder:object:root=true

// MyCRDOverriderList contains a list of MyCRDOverrider
type MyCRDOverriderList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []MyCRDOverrider `json:"items"`
}

func init() {
	SchemeBuilder.Register(&MyCRDOverrider{}, &MyCRDOverriderList{})
}

This works great for simple values, e.g.

kind: MyCRDOverrider
apiVersion: mygroup.mydomain/v1alpha1
metadata:
  name: unicorn
  namespace: template
spec:
  values:
    name: unicorn

With this template

apiVersion: templating.flanksource.com/v1
kind: Template
metadata:
  name: bash
  namespace: template
spec:
  source:
    apiVersion: mygroup.mydomain/v1alpha1
    kind: MyCRDOverrider
  resources:
    - kind: Deployment
      apiVersion: apps/v1
      metadata:
        name: bash
        namespace: template
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: bash
        template:
          metadata:
            labels:
              app: bash
          spec:
            containers:
              - image: bash
                imagePullPolicy: IfNotPresent
                command: ["bash", "-c", "sleep 99999999"]
                name: "{{.spec.values.name}}"

However, what doesn't work is putting a whole object into values, like adding the resources object.

Values:

kind: EdgeApplicationOverrider
apiVersion: edgeapplication.kubeedge/v1alpha1
metadata:
  name: unicorn
  namespace: template
spec:
  values:
    name: unicorn
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

and the template like above

...
          spec:
            containers:
              - image: bash
                imagePullPolicy: IfNotPresent
                command: ["bash", "-c", "sleep 99999999"]
                name: "{{.spec.values.name}}"
                resources: "{{.spec.values.resources}}"

The error log from template-operator is

ts=2022-11-16T10:58:58.880200737Z level=info logger=controllers.Template msg=Reconciling template=/bash template=bash
ts=2022-11-16T10:58:58.883745874Z level=info logger=controllers.Template msg="Found resources for template" template=/bash template=bash count=1
ts=2022-11-16T10:58:58.884844986Z level=error logger=controllers.Template msg="failed to ducktype object" template=/bash error="failed to duck type object: field: spec.template.spec.containers.0.resources failed to transform string to type &{[object] }: failed to transform string value to object: invalid character 'm' looking for beginning of value: invalid character 'm' looking for beginning of value" errorVerbose="invalid character 'm' looking for beginning of value\nfailed to transform string value to object: invalid character 'm' looking for beginning of value\ngithub.com/flanksource/template-operator/k8s.transformStringToType\n\t/workspace/k8s/schema_manager.go:466\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:170\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:141\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).DuckType\n\t/workspace/k8s/schema_manager.go:111\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResultObject\n\t/workspace/k8s/template_manager.go:396\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResult\n\t/workspace/k8s/template_manager.go:380\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Template\n\t/workspace/k8s/template_manager.go:372\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjects\n\t/workspace/k8s/template_manager.go:440\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjectsFromResources\n\t/workspace/k8s/template_manager.go:813\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).HandleSource\n\t/workspace/k8s/template_manager.go:249\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Run\n\t/workspace/k8s/template_manager.go:209\ngithub.com/flanksource/template-operator/controllers.(*TemplateReconciler).Reconcile\n\t/workspace/controllers/template_controller.go:92\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:298\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1.2\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:216\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:155\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:156\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:133\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.UntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:99\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1371\nfield: spec.template.spec.containers.0.resources failed to transform string to type &{[object] }\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:172\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:141\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).duckType\n\t/workspace/k8s/schema_manager.go:156\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).DuckType\n\t/workspace/k8s/schema_manager.go:111\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResultObject\n\t/workspace/k8s/template_manager.go:396\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResult\n\t/workspace/k8s/template_manager.go:380\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Template\n\t/workspace/k8s/template_manager.go:372\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjects\n\t/workspace/k8s/template_manager.go:440\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjectsFromResources\n\t/workspace/k8s/template_manager.go:813\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).HandleSource\n\t/workspace/k8s/template_manager.go:249\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Run\n\t/workspace/k8s/template_manager.go:209\ngithub.com/flanksource/template-operator/controllers.(*TemplateReconciler).Reconcile\n\t/workspace/controllers/template_controller.go:92\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:298\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1.2\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:216\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:155\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:156\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:133\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.UntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:99\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1371\nfailed to duck type object\ngithub.com/flanksource/template-operator/k8s.(*SchemaManager).DuckType\n\t/workspace/k8s/schema_manager.go:113\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResultObject\n\t/workspace/k8s/template_manager.go:396\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResult\n\t/workspace/k8s/template_manager.go:380\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Template\n\t/workspace/k8s/template_manager.go:372\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjects\n\t/workspace/k8s/template_manager.go:440\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjectsFromResources\n\t/workspace/k8s/template_manager.go:813\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).HandleSource\n\t/workspace/k8s/template_manager.go:249\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Run\n\t/workspace/k8s/template_manager.go:209\ngithub.com/flanksource/template-operator/controllers.(*TemplateReconciler).Reconcile\n\t/workspace/controllers/template_controller.go:92\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:298\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1.2\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:216\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:155\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:156\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:133\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.UntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:99\nruntime.goexit\n\t/usr/local/go/src/runtime/asm_amd64.s:1371" stacktrace="github.com/go-logr/zapr.(*zapLogger).Error\n\t/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:132\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResultObject\n\t/workspace/k8s/template_manager.go:397\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).duckTypeTemplateResult\n\t/workspace/k8s/template_manager.go:380\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Template\n\t/workspace/k8s/template_manager.go:372\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjects\n\t/workspace/k8s/template_manager.go:440\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).getObjectsFromResources\n\t/workspace/k8s/template_manager.go:813\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).HandleSource\n\t/workspace/k8s/template_manager.go:249\ngithub.com/flanksource/template-operator/k8s.(*TemplateManager).Run\n\t/workspace/k8s/template_manager.go:209\ngithub.com/flanksource/template-operator/controllers.(*TemplateReconciler).Reconcile\n\t/workspace/controllers/template_controller.go:92\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:298\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1.2\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:216\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:155\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:156\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:133\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.UntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:99"
ts=2022-11-16T10:58:58.886327813Z level=info logger=controllers.Template msg=Applying template=/bash kind=Deployment namespace=template name=bash
ts=2022-11-16T10:58:58.886450736Z level=error logger=controller-runtime.manager.controller.template msg="Reconciler error" reconcilergroup=templating.flanksource.com reconcilerkind=Template name=bash namespace= error="cannot restore struct from: string" stacktrace="github.com/go-logr/zapr.(*zapLogger).Error\n\t/go/pkg/mod/github.com/go-logr/[email protected]/zapr.go:132\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:302\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:253\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func1.2\n\t/go/pkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:216\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil.func1\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:155\nk8s.io/apimachinery/pkg/util/wait.BackoffUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:156\nk8s.io/apimachinery/pkg/util/wait.JitterUntil\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:133\nk8s.io/apimachinery/pkg/util/wait.JitterUntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:185\nk8s.io/apimachinery/pkg/util/wait.UntilWithContext\n\t/go/pkg/mod/k8s.io/[email protected]/pkg/util/wait/wait.go:99"
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant