Skip to content

Commit d69cf61

Browse files
edcdavidopenshift-merge-bot[bot]
authored andcommitted
Add OpenAPI support
ref: https://issues.redhat.com/browse/ACM-9437 Signed-off-by: David Elie-Dit-Cosaque <[email protected]> Signed-off-by: David Elie-Dit-Cosaque <[email protected]>
1 parent fb3ee74 commit d69cf61

File tree

5 files changed

+75
-18
lines changed

5 files changed

+75
-18
lines changed

docs/policygenerator-reference.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,10 @@ policies:
279279
# An example modification to the manifest
280280
annotations:
281281
friends-character: Chandler Bing
282+
# The OpenAPI schema used to merge patches (useful for non Kubernetes CRs that containt list of items)
283+
openapi:
284+
# The path to the OpenAPI schema to use when applying patches defined in patches
285+
path: ""
282286
# Optional. (See policyDefaults.categories for description.)
283287
categories:
284288
- "CM Configuration Management"

internal/patches.go

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,21 @@ package internal
44
import (
55
"errors"
66
"fmt"
7+
"os"
78
"path"
9+
"path/filepath"
810

911
yaml "gopkg.in/yaml.v3"
1012
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1113
"sigs.k8s.io/kustomize/api/krusty"
1214
"sigs.k8s.io/kustomize/kyaml/filesys"
15+
16+
"open-cluster-management.io/policy-generator-plugin/internal/types"
17+
)
18+
19+
const (
20+
localSchemaFileName = "schema.json"
21+
kustomizeDir = "kustomize"
1322
)
1423

1524
type manifestPatcher struct {
@@ -18,6 +27,7 @@ type manifestPatcher struct {
1827
// The Kustomize patches to apply on the manifests. Note that modifications are made
1928
// to the input maps. If this is an issue, provide a deep copy of the patches.
2029
patches []map[string]interface{}
30+
openAPI types.OpenAPI
2131
}
2232

2333
// validateManifestInfo verifies that the apiVersion, kind, metadata.name fields from a manifest
@@ -169,14 +179,14 @@ func (m *manifestPatcher) ApplyPatches() ([]map[string]interface{}, error) {
169179
// Create the file system in memory with the Kustomize YAML files
170180
fSys := filesys.MakeFsInMemory()
171181

172-
err := fSys.Mkdir(kustomizeDir)
182+
err := InitializeInMemoryKustomizeDir(fSys, m.openAPI.Path)
173183
if err != nil {
174-
return nil, fmt.Errorf("an unexpected error occurred when configuring Kustomize: %w", err)
184+
return nil, fmt.Errorf("failed to initialize Kustomize dir, err: %w", err)
175185
}
176186

177-
kustomizationYAMLFile := map[string][]interface{}{
178-
"resources": {},
179-
"patches": {},
187+
kustomizationYAMLFile := types.KustomizeJSON{}
188+
if m.openAPI.Path != "" {
189+
kustomizationYAMLFile.OpenAPI.Path = localSchemaFileName
180190
}
181191

182192
options := []struct {
@@ -206,13 +216,10 @@ func (m *manifestPatcher) ApplyPatches() ([]map[string]interface{}, error) {
206216
}
207217

208218
if option.kustomizeKey != "patches" {
209-
kustomizationYAMLFile[option.kustomizeKey] = append(
210-
kustomizationYAMLFile[option.kustomizeKey], manifestFileName,
211-
)
219+
kustomizationYAMLFile.Resources = append(kustomizationYAMLFile.Resources, manifestFileName)
212220
} else {
213-
kustomizationYAMLFile[option.kustomizeKey] = append(
214-
kustomizationYAMLFile[option.kustomizeKey], map[string]interface{}{"path": manifestFileName},
215-
)
221+
kustomizationYAMLFile.Patches = append(kustomizationYAMLFile.Patches,
222+
types.Patch{Path: manifestFileName})
216223
}
217224
}
218225
}
@@ -253,3 +260,27 @@ func (m *manifestPatcher) ApplyPatches() ([]map[string]interface{}, error) {
253260

254261
return manifests, nil
255262
}
263+
264+
// Initializes the in-memory file system with base directory and open API schema
265+
func InitializeInMemoryKustomizeDir(fSys filesys.FileSystem, schema string) (err error) {
266+
err = fSys.Mkdir(kustomizeDir)
267+
if err != nil {
268+
return fmt.Errorf("an unexpected error occurred when configuring Kustomize: %w", err)
269+
}
270+
271+
if schema != "" {
272+
schema = filepath.Clean(schema)
273+
274+
schemaJSON, err := os.ReadFile(schema)
275+
if err != nil {
276+
return fmt.Errorf("unable to open file: %s, err: %w ", schema, err)
277+
}
278+
279+
err = fSys.WriteFile(path.Join(kustomizeDir, localSchemaFileName), schemaJSON)
280+
if err != nil {
281+
return fmt.Errorf("error writing schema, err: %w", err)
282+
}
283+
}
284+
285+
return nil
286+
}

internal/patches_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import (
77
"testing"
88

99
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
10+
11+
"open-cluster-management.io/policy-generator-plugin/internal/types"
1012
)
1113

1214
func createExConfigMap(name string) *map[string]interface{} {
@@ -45,7 +47,9 @@ func TestValidate(t *testing.T) {
4547
},
4648
}
4749

48-
patcher := manifestPatcher{manifests: manifests, patches: patches}
50+
openAPIConfig := types.OpenAPI{Path: ""}
51+
52+
patcher := manifestPatcher{manifests: manifests, patches: patches, openAPI: openAPIConfig}
4953
err := patcher.Validate()
5054

5155
assertEqual(t, err, nil)

internal/types/types.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,33 @@ type Manifest struct {
5353
Path string `json:"path,omitempty" yaml:"path,omitempty"`
5454
ExtraDependencies []PolicyDependency `json:"extraDependencies,omitempty" yaml:"extraDependencies,omitempty"`
5555
IgnorePending bool `json:"ignorePending,omitempty" yaml:"ignorePending,omitempty"`
56+
OpenAPI `json:"openapi,omitempty" yaml:"openapi,omitempty"`
5657
}
5758

58-
type NamespaceSelector struct {
59-
Exclude []string `json:"exclude,omitempty" yaml:"exclude,omitempty"`
60-
Include []string `json:"include,omitempty" yaml:"include,omitempty"`
61-
MatchLabels *map[string]string `json:"matchLabels,omitempty" yaml:"matchLabels,omitempty"`
62-
MatchExpressions *[]metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty" yaml:"matchExpressions,omitempty"`
59+
type OpenAPI struct {
60+
Path string `yaml:"path"`
6361
}
6462

63+
type KustomizeJSON struct {
64+
OpenAPI `json:"openapi,omitempty" yaml:"openapi,omitempty"`
65+
Patches []Patch `json:"patches" yaml:"patches"`
66+
Resources []string `json:"resources" yaml:"resources"`
67+
}
68+
69+
type Patch struct {
70+
Path string `yaml:"path,omitempty" json:"path,omitempty"`
71+
}
72+
73+
type (
74+
Resources []string
75+
NamespaceSelector struct {
76+
Exclude []string `json:"exclude,omitempty" yaml:"exclude,omitempty"`
77+
Include []string `json:"include,omitempty" yaml:"include,omitempty"`
78+
MatchLabels *map[string]string `json:"matchLabels,omitempty" yaml:"matchLabels,omitempty"`
79+
MatchExpressions *[]metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty" yaml:"matchExpressions,omitempty"`
80+
}
81+
)
82+
6583
// Define String() so that the LabelSelector is dereferenced in the logs
6684
func (t NamespaceSelector) String() string {
6785
fmtSelectorStr := "{include:%s,exclude:%s,matchLabels:%+v,matchExpressions:%+v}"

internal/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ func getManifests(policyConf *types.PolicyConfig) ([][]map[string]interface{}, e
123123
}
124124

125125
if len(manifest.Patches) > 0 {
126-
patcher := manifestPatcher{manifests: manifestFiles, patches: manifest.Patches}
126+
patcher := manifestPatcher{manifests: manifestFiles, patches: manifest.Patches, openAPI: manifest.OpenAPI}
127127
const errTemplate = `failed to process the manifest at "%s": %w`
128128

129129
err = patcher.Validate()

0 commit comments

Comments
 (0)