1 package unpack
2
3 import (
4 "fmt"
5
6 v1 "github.com/google/go-containerregistry/pkg/v1"
7 "sigs.k8s.io/kustomize/api/filters/namespace"
8
9 "edge-infra.dev/pkg/f8n/warehouse/cluster"
10 "edge-infra.dev/pkg/f8n/warehouse/lift"
11 "edge-infra.dev/pkg/f8n/warehouse/lift/render"
12 "edge-infra.dev/pkg/f8n/warehouse/oci"
13 "edge-infra.dev/pkg/f8n/warehouse/oci/layer"
14 "edge-infra.dev/pkg/f8n/warehouse/pallet"
15 )
16
17
18
19 func Layers(a oci.Artifact, opts ...Option) ([]layer.Layer, error) {
20 options, err := makeOptions(opts...)
21 if err != nil {
22 return nil, err
23 }
24
25
26 switch a := a.(type) {
27
28
29 case pallet.Pallet:
30
31 if _, ok := a.Unwrap().(v1.Image); !ok && options.provider == "" {
32 return nil, fmt.Errorf(
33 "%s: %s pallet requires one of %s",
34 cluster.ErrNoProviders, a.Name(), a.Providers(),
35 )
36 }
37 return unpackPallet(a, *options)
38 case v1.ImageIndex:
39 if options.provider == "" {
40 return nil, fmt.Errorf(
41 "%s: v1.ImageIndex requires a provider",
42 cluster.ErrNoProviders,
43 )
44 }
45 }
46
47
48 p, err := pallet.New(a)
49 if err != nil {
50 return nil, err
51 }
52
53 return unpackPallet(p, *options)
54 }
55
56
57 func unpackPallet(p pallet.Pallet, opts options) ([]layer.Layer, error) {
58
59 layers, err := p.Layers(opts.provider)
60 if err != nil {
61 return nil, err
62 }
63
64 switch p.Renderable() {
65
66 case true:
67 params := map[string]string{lift.PalletNameRenderingParameter: p.Name()}
68
69
70 if opts.provider != "" {
71 params[lift.ClusterProviderRenderingParameter] = string(opts.provider)
72 }
73 opts.parameters = append(opts.parameters, params)
74 case false:
75 opts.render = false
76 }
77
78
79 if len(opts.keys) == 0 && len(opts.types) == 0 {
80 for i, l := range layers {
81 layers[i], err = processLayer(l, p.Parameters(), opts)
82 if err != nil {
83 return nil, err
84 }
85 }
86
87 return layers, nil
88 }
89
90
91 return filterLayers(layers, p.Parameters(), opts)
92 }
93
94
95
96 func filterLayers(layers []layer.Layer, palletParams []string, opts options) ([]layer.Layer, error) {
97 var (
98 err error
99 j = 0
100 )
101
102
103 for _, l := range layers {
104
105
106 for _, desired := range opts.keys {
107 if l.Key() == desired {
108 l, err = processLayer(l, palletParams, opts)
109 if err != nil {
110 return nil, err
111 }
112
113 layers[j] = l
114 j++
115 }
116 }
117
118 for _, t := range opts.types {
119 if l.Type() == t {
120 l, err = processLayer(l, palletParams, opts)
121 if err != nil {
122 return nil, err
123 }
124
125 layers[j] = l
126 j++
127 }
128 }
129 }
130 layers = layers[:j]
131
132 return layers, nil
133 }
134
135 func processLayer(l layer.Layer, palletParams []string, opts options) (layer.Layer, error) {
136 var err error
137
138 if opts.render {
139 l, err = render.Layer(l, palletParams, opts.parameters...)
140 if err != nil {
141 return nil, err
142 }
143 }
144
145 if opts.infraNamespace != "" && l.Type() == layer.Infra {
146 l, err = layer.Filter(l, namespace.Filter{Namespace: opts.infraNamespace})
147 if err != nil {
148 return nil, err
149 }
150 }
151
152 return l, nil
153 }
154
View as plain text