...
1 package validate
2
3 import (
4 "fmt"
5
6 v1 "github.com/google/go-containerregistry/pkg/v1"
7
8 wh "edge-infra.dev/pkg/f8n/warehouse"
9 "edge-infra.dev/pkg/f8n/warehouse/cluster"
10 "edge-infra.dev/pkg/f8n/warehouse/oci"
11 "edge-infra.dev/pkg/f8n/warehouse/oci/layer"
12 "edge-infra.dev/pkg/f8n/warehouse/pallet"
13 )
14
15
16 func Pallet(p pallet.Pallet) error {
17
18 if err := Warehouse(p); err != nil {
19 return err
20 }
21
22
23 err := Validate(p, &Fns{
24 Index: palletValidateIndex,
25 Image: palletValidateImage,
26 Layer: palletValidateLayer,
27 })
28 if err != nil {
29 return fmt.Errorf("invalid Pallet artifact: %v", err)
30 }
31 return nil
32 }
33
34 func palletValidateIndex(idx oci.Artifact, rootAnnotations map[string]string) error {
35 annotations, err := oci.Annotations(idx)
36 if err != nil {
37 return err
38 }
39
40
41 if err := Annotations(annotations, palletAnnotationValidators, palletOptionalAnnotationValidators); err != nil {
42 return err
43 }
44
45
46 if err := validatePalletAgainstRoot(annotations, rootAnnotations); err != nil {
47 return err
48 }
49
50 idxName := annotations[wh.AnnotationName]
51 palletClusterProviders, err := cluster.ProvidersFromAnnotations(annotations)
52 if err != nil {
53 return err
54 }
55
56 i := idx.(v1.ImageIndex)
57 idxManifest, err := i.IndexManifest()
58 if err != nil {
59 return err
60 }
61
62
63 for n, manifest := range idxManifest.Manifests {
64 if err := validatePalletManifest(manifest, idxName, palletClusterProviders); err != nil {
65 return fmt.Errorf("manifest %d is invalid: %v", n, err)
66 }
67 }
68
69 return nil
70 }
71
72 func validatePalletManifest(manifest v1.Descriptor, idxName string, palletClusterProviders cluster.Providers) error {
73 annotations := manifest.Annotations
74
75
76 if err := Annotations(annotations, palletManifestAnnotationValidators, nil); err != nil {
77 return err
78 }
79
80
81 if annotations[wh.AnnotationRefName] != idxName {
82 return nil
83 }
84
85
86 clusterProviders, err := cluster.ProvidersFromAnnotations(annotations)
87 if err != nil {
88 return err
89 }
90 for _, provider := range clusterProviders {
91 if err := palletClusterProviders.IsValid(provider); err != nil {
92 return err
93 }
94 }
95
96 return nil
97 }
98
99 func palletValidateImage(img oci.Artifact, rootAnnotations map[string]string) error {
100 annotations, err := oci.Annotations(img)
101 if err != nil {
102 return err
103 }
104
105
106 if err := Annotations(annotations, palletAnnotationValidators, palletOptionalAnnotationValidators); err != nil {
107 return err
108 }
109
110
111 if err := validatePalletAgainstRoot(annotations, rootAnnotations); err != nil {
112 return err
113 }
114
115 i := img.(v1.Image)
116 layers, err := layer.FromImage(i)
117 if err != nil {
118 return err
119 }
120
121 numBaseLayers := 0
122 numInfraLayers := 0
123 for _, l := range layers {
124 layerAnnotations := l.Annotations()
125 switch l.Type() {
126 case layer.Infra:
127 numInfraLayers++
128 case layer.Runtime:
129 if _, ok := layerAnnotations[wh.AnnotationLayerRuntimeCapability]; !ok {
130 numBaseLayers++
131 }
132 }
133 }
134
135
136 if numBaseLayers > 1 {
137 return NewImageLayersError(errMultipleBaseLayers, numBaseLayers)
138 }
139
140
141 if numInfraLayers > 1 {
142 return NewImageLayersError(errMultipleInfraLayers, numInfraLayers)
143 }
144
145 return nil
146 }
147
148 func palletValidateLayer(l layer.Layer, _ map[string]string) error {
149
150 if _, err := l.Unstructured(); err != nil {
151 return fmt.Errorf("%v: %v", errLayersMustBeK8sManifests, err)
152 }
153
154 return nil
155 }
156
View as plain text