Skip to content

Commit 2799c77

Browse files
committed
Add empty CRD description validator
Operator-SDK has alpha support for running external validators. Validators are implemented as binaries that are given a path to bundle and print the result of the validation to the standard out. More information is available at operator-framework/enhancements#98. This commit adds in an external validator that errors when a CRD specified in the bundle `ClusterServiceVersion` does not have a description. This is enforced for both owned and required CRDs. Signed-off-by: Ryan King <[email protected]>
1 parent 697a426 commit 2799c77

File tree

1 file changed

+96
-0
lines changed
  • cmd/validators/no-empty-crd-description

1 file changed

+96
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2019 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package main
15+
16+
import (
17+
"encoding/json"
18+
"fmt"
19+
"os"
20+
"path/filepath"
21+
22+
apimanifests "github.com/operator-framework/api/pkg/manifests"
23+
apierrors "github.com/operator-framework/api/pkg/validation/errors"
24+
registrybundle "github.com/operator-framework/operator-registry/pkg/lib/bundle"
25+
"github.com/operator-framework/operator-sdk/internal/registry"
26+
)
27+
28+
func main() {
29+
if len(os.Args) < 2 {
30+
fmt.Printf("usage: %s <bundle root>\n", os.Args[0])
31+
os.Exit(1)
32+
}
33+
34+
bundle, _, err := getBundleDataFromDir(os.Args[1])
35+
if err != nil {
36+
fmt.Printf("problem getting bundle [%s] data, %v\n", os.Args[1], err)
37+
os.Exit(1)
38+
}
39+
40+
var (
41+
ownedCRDs = bundle.CSV.Spec.CustomResourceDefinitions.Owned
42+
requiredCRDs = bundle.CSV.Spec.CustomResourceDefinitions.Required
43+
result = apierrors.ManifestResult{
44+
Name: bundle.Name,
45+
Warnings: []apierrors.Error{},
46+
Errors: make([]apierrors.Error, 0, len(ownedCRDs)+len(requiredCRDs)),
47+
}
48+
enc = json.NewEncoder(os.Stdout)
49+
)
50+
51+
for _, crd := range append(ownedCRDs, requiredCRDs...) {
52+
if crd.Description == "" {
53+
result.Errors = append(result.Errors, makeEmptyCrdDescriptionError(crd.DisplayName))
54+
}
55+
}
56+
57+
enc.SetIndent("", " ")
58+
if err := enc.Encode(result); err != nil {
59+
fmt.Printf("XXX ERROR: %v\n", err)
60+
}
61+
}
62+
63+
// getBundleDataFromDir returns the bundle object and associated metadata from dir, if any.
64+
func getBundleDataFromDir(dir string) (*apimanifests.Bundle, string, error) {
65+
// Gather bundle metadata.
66+
metadata, _, err := registry.FindBundleMetadata(dir)
67+
if err != nil {
68+
return nil, "", err
69+
}
70+
manifestsDirName, hasLabel := metadata.GetManifestsDir()
71+
if !hasLabel {
72+
manifestsDirName = registrybundle.ManifestsDir
73+
}
74+
manifestsDir := filepath.Join(dir, manifestsDirName)
75+
// Detect mediaType.
76+
mediaType, err := registrybundle.GetMediaType(manifestsDir)
77+
if err != nil {
78+
return nil, "", err
79+
}
80+
// Read the bundle.
81+
bundle, err := apimanifests.GetBundleFromDir(manifestsDir)
82+
if err != nil {
83+
return nil, "", err
84+
}
85+
return bundle, mediaType, nil
86+
}
87+
88+
func makeEmptyCrdDescriptionError(displayName string) apierrors.Error {
89+
return apierrors.Error{
90+
Type: apierrors.ErrorFieldMissing,
91+
Level: apierrors.LevelError,
92+
Field: displayName,
93+
BadValue: "",
94+
Detail: "CRD descriptions cannot be empty",
95+
}
96+
}

0 commit comments

Comments
 (0)