@@ -2,24 +2,82 @@ package revision
22
33import (
44 "context"
5+ "io"
6+ "io/fs"
57
8+ "github.com/google/go-containerregistry/pkg/v1/mutate"
9+ "google.golang.org/protobuf/proto"
10+ "google.golang.org/protobuf/types/known/anypb"
11+ apierrors "k8s.io/apimachinery/pkg/api/errors"
612 "k8s.io/client-go/tools/record"
713 "sigs.k8s.io/controller-runtime/pkg/client"
814 "sigs.k8s.io/controller-runtime/pkg/log"
915 "sigs.k8s.io/controller-runtime/pkg/reconcile"
16+
17+ "namespacelabs.dev/foundation/internal/artifacts/oci"
18+ "namespacelabs.dev/foundation/internal/compute"
19+ "namespacelabs.dev/foundation/internal/fnerrors"
20+ "namespacelabs.dev/foundation/internal/fnfs/tarfs"
21+ "namespacelabs.dev/foundation/schema"
1022)
1123
1224type RevisionReconciler struct {
13- client client.Client
25+ clt client.Client
1426 recorder record.EventRecorder
1527}
1628
1729func (r * RevisionReconciler ) Reconcile (ctx context.Context , req reconcile.Request ) (reconcile.Result , error ) {
1830 log := log .FromContext (ctx )
19-
2031 log .Info ("Reconciling" , "name" , req .NamespacedName )
2132
22- // TODO: actually act on the Revision CRD
33+ var rev Revision
34+ err := r .clt .Get (ctx , req .NamespacedName , & rev )
35+ if err != nil {
36+ if apierrors .IsNotFound (err ) {
37+ // TODO: handle delete use-case
38+ return reconcile.Result {}, nil
39+ }
40+ log .Error (err , "failed to get Revision" )
41+ return reconcile.Result {}, err
42+ }
43+
44+ plan , err := loadPlan (ctx , rev .Spec .Image )
45+ if err != nil {
46+ log .Error (err , "failed to load plan" )
47+ return reconcile.Result {Requeue : true }, err
48+ }
49+
50+ log .Info ("got plan" , "plan" , plan .String ())
2351
2452 return reconcile.Result {}, nil
2553}
54+
55+ func loadPlan (ctx context.Context , path string ) (* schema.DeployPlan , error ) {
56+ raw , err := loadPlanContents (ctx , path )
57+ if err != nil {
58+ return nil , fnerrors .New ("failed to load %q: %w" , path , err )
59+ }
60+
61+ any := & anypb.Any {}
62+ if err := proto .Unmarshal (raw , any ); err != nil {
63+ return nil , fnerrors .New ("failed to unmarshal %q: %w" , path , err )
64+ }
65+
66+ plan := & schema.DeployPlan {}
67+ if err := any .UnmarshalTo (plan ); err != nil {
68+ return nil , fnerrors .New ("failed to unmarshal %q: %w" , path , err )
69+ }
70+
71+ return plan , nil
72+ }
73+
74+ func loadPlanContents (ctx context.Context , path string ) ([]byte , error ) {
75+ image , err := compute .GetValue (ctx , oci .ImageP (path , nil , oci.ResolveOpts {}))
76+ if err != nil {
77+ return nil , err
78+ }
79+
80+ fsys := tarfs.FS {TarStream : func () (io.ReadCloser , error ) { return mutate .Extract (image ), nil }}
81+
82+ return fs .ReadFile (fsys , "deployplan.binarypb" )
83+ }
0 commit comments