@@ -20,16 +20,23 @@ import (
20
20
"bytes"
21
21
"context"
22
22
"fmt"
23
+ "os"
24
+ "os/exec"
25
+ "path"
26
+ "runtime"
23
27
"sort"
24
28
"strings"
29
+ "time"
25
30
26
31
"github.com/go-logr/logr"
27
32
"github.com/google/go-containerregistry/pkg/authn/k8schain"
28
33
"github.com/vmware-labs/reconciler-runtime/apis"
29
34
"github.com/vmware-labs/reconciler-runtime/reconcilers"
30
35
"github.com/vmware-labs/reconciler-runtime/tracker"
36
+ "gopkg.in/yaml.v2"
31
37
corev1 "k8s.io/api/core/v1"
32
38
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
33
40
"k8s.io/apimachinery/pkg/labels"
34
41
"k8s.io/apimachinery/pkg/runtime/schema"
35
42
"k8s.io/apimachinery/pkg/types"
@@ -132,18 +139,46 @@ func ResolveConventions() reconcilers.SubReconciler {
132
139
convention .ClientConfig = * clientConfig
133
140
} else if source .Spec .Ytt != nil {
134
141
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
+
138
147
// 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 )
140
150
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
+ }
146
158
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
+ // }
147
182
return nil
148
183
}
149
184
conventions = append (conventions , convention )
@@ -162,6 +197,50 @@ func ResolveConventions() reconcilers.SubReconciler {
162
197
}
163
198
}
164
199
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
+
165
244
// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch
166
245
// +kubebuilder:rbac:groups=core,resources=serviceaccounts,verbs=get;list;watch
167
246
0 commit comments