Skip to content

Commit d0d2595

Browse files
committed
add ytt invocation
1 parent 8bd396f commit d0d2595

File tree

4 files changed

+129
-12
lines changed

4 files changed

+129
-12
lines changed

cleanup.sh

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
set -euo pipefail
2+
3+
# make sure to regenerate manifests and run tests
4+
make all
5+
6+
# delete any existing convention and deployment
7+
kubectl delete -f samples/ytt-based-conventions/ytt-example.yaml
8+
kapp delete -a conventions -n cartographer-system
9+
10+
# create a new deployment
11+
kapp deploy -n cartographer-system -a conventions -f <( \
12+
ko resolve -f <( \
13+
ytt \
14+
-f dist/cartographer-conventions.yaml
15+
) \
16+
)
17+
18+
# create the ytt based convention
19+
kubectl apply -f samples/ytt-based-conventions/ytt-example.yaml
20+
#kubectl delete -f samples/ytt-based-conventions/ytt-example.yaml
21+
22+
# inspect the ytt based convention
23+
kubectl get clusterpodconvention.conventions.carto.run/spring-ytt-sample -o yaml
24+
25+
# create a workload
26+
kubectl apply -f samples/ytt-based-conventions/workload.yaml
27+
#kubectl delete -f samples/ytt-based-conventions/workload.yaml

pkg/apis/conventions/v1alpha1/clusterpodconvention_validation.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@ func (s *ClusterPodConventionSpec) Validate() validation.FieldErrors {
8282
errs = errs.Also(s.Webhook.Validate().ViaField("webhook"))
8383
}
8484
// only invoke ytt validations if the webhook configuration is not being used
85-
if s.Webhook == nil && s.Ytt != nil {
86-
errs = errs.Also(s.Webhook.Validate().ViaField("ytt"))
87-
}
85+
// if s.Webhook == nil && s.Ytt != nil {
86+
// errs = errs.Also(s.Ytt.Validate().ViaField("ytt"))
87+
// }
8888
}
8989

9090
if s.SelectorTarget != PodTemplateSpecLabels && s.SelectorTarget != PodIntentLabels {

pkg/controllers/podintent_reconciler.go

+88-9
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,23 @@ import (
2020
"bytes"
2121
"context"
2222
"fmt"
23+
"os"
24+
"os/exec"
25+
"path"
26+
"runtime"
2327
"sort"
2428
"strings"
29+
"time"
2530

2631
"github.com/go-logr/logr"
2732
"github.com/google/go-containerregistry/pkg/authn/k8schain"
2833
"github.com/vmware-labs/reconciler-runtime/apis"
2934
"github.com/vmware-labs/reconciler-runtime/reconcilers"
3035
"github.com/vmware-labs/reconciler-runtime/tracker"
36+
"gopkg.in/yaml.v2"
3137
corev1 "k8s.io/api/core/v1"
3238
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3340
"k8s.io/apimachinery/pkg/labels"
3441
"k8s.io/apimachinery/pkg/runtime/schema"
3542
"k8s.io/apimachinery/pkg/types"
@@ -132,18 +139,46 @@ func ResolveConventions() reconcilers.SubReconciler {
132139
convention.ClientConfig = *clientConfig
133140
} else if source.Spec.Ytt != nil {
134141
log.Info("handling a ytt based convention")
135-
// read template spec and convenert to a sptream of bytes
136-
// template
137-
template := &parent.Spec.Template
142+
143+
// read template spec and convert to string
144+
template := parent.Spec.Template.AsPodTemplateSpec()
145+
log.Info("retrieved pod template spec from the workload", template.String())
146+
138147
// convert template as a stream of bytes
139-
// templatesAsBytes = bytes.NewBuffer([]byte(template(string)))
148+
templatesAsBytes := bytes.NewBuffer([]byte(template.String()))
149+
log.Info("template spec as a stream of bytes", templatesAsBytes)
140150

141-
// convert template to a stream of bytes
142-
// kubectl = "kubectl"
143-
// ytt = "ytt"
144-
// args
145-
log.Info("your template spec", template.GetObjectMeta())
151+
// setup stdin and stdout for ytt invocation
152+
ytt := "ytt"
153+
154+
// ko copies the content of the kodata directory into the container at a path referenced by $KO_DATA_PATH
155+
if kodata, ok := os.LookupEnv("KO_DATA_PATH"); ok {
156+
ytt = path.Join(kodata, fmt.Sprintf("ytt-%s-%s", runtime.GOOS, runtime.GOARCH))
157+
}
146158

159+
args := []string{"--version"}
160+
cmd := exec.CommandContext(ctx, ytt, args...)
161+
162+
stdout := bytes.NewBuffer([]byte{})
163+
stderr := bytes.NewBuffer([]byte{})
164+
// stderr := bytes.NewBuffer([]byte{})
165+
166+
cmd.Stdin = templatesAsBytes
167+
cmd.Stdout = stdout
168+
cmd.Stderr = stderr
169+
170+
log.Info("ytt call", "args", args, "input", template)
171+
cmd.Run()
172+
// if err := cmd.Run(); err != nil {
173+
// msg := stderr.String()
174+
// if msg == "" {
175+
// log.Error(err, "unable to apply ytt for", "ClusterPodConvention", msg)
176+
// return nil
177+
// }
178+
// output := stdout.String()
179+
// log.Info("ytt result", "output", output)
180+
// return nil
181+
// }
147182
return nil
148183
}
149184
conventions = append(conventions, convention)
@@ -162,6 +197,50 @@ func ResolveConventions() reconcilers.SubReconciler {
162197
}
163198
}
164199

200+
func ApplyYtt(ctx context.Context, template conventionsv1alpha1.PodTemplateSpec) (interface{}, error) {
201+
log := logr.FromContextOrDiscard(ctx)
202+
203+
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
204+
defer cancel()
205+
206+
ytt := "ytt"
207+
if kodata, ok := os.LookupEnv("KO_DATA_PATH"); ok {
208+
ytt = path.Join(kodata, fmt.Sprintf("ytt-%s-%s", runtime.GOOS, runtime.GOARCH))
209+
}
210+
211+
args := []string{"--", "version"}
212+
stdin := bytes.NewReader([]byte(template.Spec.String()))
213+
stdout := bytes.NewBuffer([]byte{})
214+
stderr := bytes.NewBuffer([]byte{})
215+
216+
cmd := exec.CommandContext(ctx, ytt, args...)
217+
cmd.Stdin = stdin
218+
cmd.Stdout = stdout
219+
cmd.Stderr = stderr
220+
221+
log.Info("ytt call args", args)
222+
log.Info("ytt call input", template)
223+
224+
if err := cmd.Run(); err != nil {
225+
msg := stderr.String()
226+
if msg == "" {
227+
log.Error(err, "failed handle ytt")
228+
return nil, err
229+
}
230+
return nil, err
231+
}
232+
output := stdout.String()
233+
log.Info("ytt result", "output", output)
234+
235+
stampedObject := &unstructured.Unstructured{}
236+
log.Info("your stamped object", stampedObject)
237+
if err := yaml.Unmarshal([]byte(output), stampedObject); err != nil {
238+
// ytt should never return invalid yaml
239+
return nil, err
240+
}
241+
return stampedObject, nil
242+
}
243+
165244
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch
166245
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch
167246

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
apiVersion: conventions.carto.run/v1alpha1
3+
kind: PodIntent
4+
metadata:
5+
name: spring-sample
6+
spec:
7+
template:
8+
spec:
9+
containers:
10+
- name: workload
11+
image: scothis/petclinic:sbom-20211210@sha256:8b517f21f283229e855e316e2753396239884eb9c4009ab6c797bdf2a041140f

0 commit comments

Comments
 (0)