Skip to content

Commit 6afd668

Browse files
committed
add ytt invocation
1 parent 8bd396f commit 6afd668

File tree

4 files changed

+102
-16
lines changed

4 files changed

+102
-16
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

+61-13
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,19 +139,15 @@ 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
138-
// convert template as a stream of bytes
139-
// templatesAsBytes = bytes.NewBuffer([]byte(template(string)))
140-
141-
// convert template to a stream of bytes
142-
// kubectl = "kubectl"
143-
// ytt = "ytt"
144-
// args
145-
log.Info("your template spec", template.GetObjectMeta())
146-
147-
return nil
142+
143+
// read template spec and convert to string
144+
145+
log.Info("retrieved pod template spec from the workload", parent)
146+
stampedObj, err := ApplyYtt(ctx, *parent)
147+
if err != nil {
148+
return nil
149+
}
150+
log.Info("stamped out object", stampedObj)
148151
}
149152
conventions = append(conventions, convention)
150153
}
@@ -162,6 +165,51 @@ func ResolveConventions() reconcilers.SubReconciler {
162165
}
163166
}
164167

168+
func ApplyYtt(ctx context.Context, workload conventionsv1alpha1.PodIntent) (interface{}, error) {
169+
template := workload.Spec.Template.AsPodTemplateSpec()
170+
log := logr.FromContextOrDiscard(ctx)
171+
172+
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
173+
defer cancel()
174+
175+
ytt := "ytt"
176+
if kodata, ok := os.LookupEnv("KO_DATA_PATH"); ok {
177+
ytt = path.Join(kodata, fmt.Sprintf("ytt-%s-%s", runtime.GOOS, runtime.GOARCH))
178+
}
179+
180+
args := []string{"--version"}
181+
stdin := bytes.NewReader([]byte(template.Spec.String()))
182+
stdout := bytes.NewBuffer([]byte{})
183+
stderr := bytes.NewBuffer([]byte{})
184+
185+
cmd := exec.CommandContext(ctx, ytt, args...)
186+
cmd.Stdin = stdin
187+
cmd.Stdout = stdout
188+
cmd.Stderr = stderr
189+
190+
log.Info("ytt call args", args)
191+
log.Info("ytt call input", template)
192+
193+
if err := cmd.Run(); err != nil {
194+
msg := stderr.String()
195+
if msg == "" {
196+
log.Error(err, "failed handle ytt")
197+
return nil, err
198+
}
199+
return nil, err
200+
}
201+
output := stdout.String()
202+
log.Info("ytt result", "output", output)
203+
204+
stampedObject := &unstructured.Unstructured{}
205+
log.Info("your stamped object", stampedObject)
206+
if err := yaml.Unmarshal([]byte(output), stampedObject); err != nil {
207+
// ytt should never return invalid yaml
208+
return nil, err
209+
}
210+
return stampedObject, nil
211+
}
212+
165213
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch
166214
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch
167215

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)