Skip to content

Commit 65b687b

Browse files
author
Eric Stroczynski
authored
internal/pkg/scaffold: move some utility functions to internal/util/k8sutil (#1635)
1 parent 8631041 commit 65b687b

File tree

11 files changed

+249
-187
lines changed

11 files changed

+249
-187
lines changed

internal/pkg/scaffold/crd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ func (s *CRD) CustomRender() ([]byte, error) {
142142
}
143143

144144
setCRDVersions(crd)
145-
return k8sutil.GetObjectBytes(crd)
145+
return k8sutil.GetObjectBytes(crd, yaml.Marshal)
146146
}
147147

148148
func newCRDForResource(r *Resource) *apiextv1beta1.CustomResourceDefinition {

internal/pkg/scaffold/olm-catalog/csv.go

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import (
2323
"path/filepath"
2424
"strings"
2525
"sync"
26-
"unicode"
2726

2827
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
2928
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
@@ -138,7 +137,7 @@ func (s *CSV) CustomRender() ([]byte, error) {
138137
}
139138
}
140139

141-
return k8sutil.GetObjectBytes(csv)
140+
return k8sutil.GetObjectBytes(csv, yaml.Marshal)
142141
}
143142

144143
func (s *CSV) getBaseCSVIfExists() (*olmapiv1alpha1.ClusterServiceVersion, bool, error) {
@@ -190,41 +189,6 @@ func (s *CSV) getCSVPath(ver string) string {
190189
return filepath.Join(s.pathPrefix, OLMCatalogDir, lowerProjName, ver, name)
191190
}
192191

193-
// getDisplayName turns a project dir name in any of {snake, chain, camel}
194-
// cases, hierarchical dot structure, or space-delimited into a
195-
// space-delimited, title'd display name.
196-
// Ex. "another-_AppOperator_againTwiceThrice More"
197-
// -> "Another App Operator Again Twice Thrice More"
198-
func getDisplayName(name string) string {
199-
for _, sep := range ".-_ " {
200-
splitName := strings.Split(name, string(sep))
201-
for i := 0; i < len(splitName); i++ {
202-
if splitName[i] == "" {
203-
splitName = append(splitName[:i], splitName[i+1:]...)
204-
i--
205-
} else {
206-
splitName[i] = strings.TrimSpace(splitName[i])
207-
}
208-
}
209-
name = strings.Join(splitName, " ")
210-
}
211-
splitName := strings.Split(name, " ")
212-
for i, word := range splitName {
213-
temp := word
214-
o := 0
215-
for j, r := range word {
216-
if unicode.IsUpper(r) {
217-
if j > 0 && !unicode.IsUpper(rune(word[j-1])) {
218-
temp = temp[0:j+o] + " " + temp[j+o:len(temp)]
219-
o++
220-
}
221-
}
222-
}
223-
splitName[i] = temp
224-
}
225-
return strings.TrimSpace(strings.Title(strings.Join(splitName, " ")))
226-
}
227-
228192
// initCSVFields initializes all csv fields that should be populated by a user
229193
// with sane defaults. initCSVFields should only be called for new csv's.
230194
func (s *CSV) initCSVFields(csv *olmapiv1alpha1.ClusterServiceVersion) {
@@ -237,7 +201,7 @@ func (s *CSV) initCSVFields(csv *olmapiv1alpha1.ClusterServiceVersion) {
237201

238202
// Spec fields
239203
csv.Spec.Version = *semver.New(s.CSVVersion)
240-
csv.Spec.DisplayName = getDisplayName(s.OperatorName)
204+
csv.Spec.DisplayName = k8sutil.GetDisplayName(s.OperatorName)
241205
csv.Spec.Description = "Placeholder description"
242206
csv.Spec.Maturity = "alpha"
243207
csv.Spec.Provider = olmapiv1alpha1.AppLink{}
@@ -371,7 +335,7 @@ func (s *CSV) updateCSVFromManifestFiles(cfg *CSVConfig, csv *olmapiv1alpha1.Clu
371335
scanner := yamlutil.NewYAMLScanner(yamlData)
372336
for scanner.Scan() {
373337
yamlSpec := scanner.Bytes()
374-
kind, err := getKindfromYAML(yamlSpec)
338+
kind, err := k8sutil.GetKindfromYAML(yamlSpec)
375339
if err != nil {
376340
return fmt.Errorf("%s: %v", f, err)
377341
}

internal/pkg/scaffold/olm-catalog/csv_test.go

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -167,33 +167,6 @@ func TestUpdateVersion(t *testing.T) {
167167
}
168168
}
169169

170-
func TestGetDisplayName(t *testing.T) {
171-
cases := []struct {
172-
input, wanted string
173-
}{
174-
{"Appoperator", "Appoperator"},
175-
{"appoperator", "Appoperator"},
176-
{"appoperatoR", "Appoperato R"},
177-
{"AppOperator", "App Operator"},
178-
{"appOperator", "App Operator"},
179-
{"app-operator", "App Operator"},
180-
{"app-_operator", "App Operator"},
181-
{"App-operator", "App Operator"},
182-
{"app-_Operator", "App Operator"},
183-
{"app--Operator", "App Operator"},
184-
{"app--_Operator", "App Operator"},
185-
{"APP", "APP"},
186-
{"another-AppOperator_againTwiceThrice More", "Another App Operator Again Twice Thrice More"},
187-
}
188-
189-
for _, c := range cases {
190-
dn := getDisplayName(c.input)
191-
if dn != c.wanted {
192-
t.Errorf("Wanted %s, got %s", c.wanted, dn)
193-
}
194-
}
195-
}
196-
197170
func TestSetAndCheckOLMNamespaces(t *testing.T) {
198171
depBytes, err := ioutil.ReadFile(filepath.Join(testDeployDir, "operator.yaml"))
199172
if err != nil {

internal/pkg/scaffold/olm-catalog/csv_updaters.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,6 @@ func (s *updaterStore) Apply(csv *olmapiv1alpha1.ClusterServiceVersion) error {
6969
return nil
7070
}
7171

72-
func getKindfromYAML(yamlData []byte) (string, error) {
73-
var temp struct {
74-
Kind string
75-
}
76-
if err := yaml.Unmarshal(yamlData, &temp); err != nil {
77-
return "", err
78-
}
79-
return temp.Kind, nil
80-
}
81-
8272
func (s *updaterStore) AddToUpdater(yamlSpec []byte, kind string) (found bool, err error) {
8373
found = true
8474
switch kind {

internal/pkg/scaffold/olm-catalog/package_manifest.go

Lines changed: 2 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package catalog
1616

1717
import (
18-
"fmt"
1918
"io/ioutil"
2019
"os"
2120
"path/filepath"
@@ -24,6 +23,7 @@ import (
2423

2524
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
2625
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
26+
registryutil "github.com/operator-framework/operator-sdk/internal/util/operator-registry"
2727

2828
"github.com/ghodss/yaml"
2929
olmregistry "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
@@ -95,7 +95,7 @@ func (s *PackageManifest) CustomRender() ([]byte, error) {
9595
return nil, errors.Wrapf(err, "package manifest %s", path)
9696
}
9797

98-
if err := validatePackageManifest(pm); err != nil {
98+
if err := registryutil.ValidatePackageManifest(pm); err != nil {
9999
return nil, errors.Wrapf(err, "failed to validate package manifest %s", pm.PackageName)
100100
}
101101

@@ -127,37 +127,6 @@ func (s *PackageManifest) newPackageManifest() *olmregistry.PackageManifest {
127127
return pm
128128
}
129129

130-
func validatePackageManifest(pm *olmregistry.PackageManifest) error {
131-
if pm.PackageName == "" {
132-
return fmt.Errorf("package name cannot be empty")
133-
}
134-
if len(pm.Channels) == 0 {
135-
return fmt.Errorf("channels cannot be empty")
136-
}
137-
if pm.DefaultChannelName == "" {
138-
return fmt.Errorf("default channel cannot be empty")
139-
}
140-
141-
seen := map[string]struct{}{}
142-
for i, c := range pm.Channels {
143-
if c.Name == "" {
144-
return fmt.Errorf("channel %d name cannot be empty", i)
145-
}
146-
if c.CurrentCSVName == "" {
147-
return fmt.Errorf("channel %s currentCSV cannot be empty", c.Name)
148-
}
149-
if _, ok := seen[c.Name]; ok {
150-
return fmt.Errorf("duplicate package manifest channel name %s; channel names must be unique", c.Name)
151-
}
152-
seen[c.Name] = struct{}{}
153-
}
154-
if _, ok := seen[pm.DefaultChannelName]; !ok {
155-
return fmt.Errorf("default channel %s does not exist in channels", pm.DefaultChannelName)
156-
}
157-
158-
return nil
159-
}
160-
161130
// setChannels checks for duplicate channels in pm and sets the default
162131
// channel if possible.
163132
func (s *PackageManifest) setChannels(pm *olmregistry.PackageManifest) error {

internal/pkg/scaffold/olm-catalog/package_manifest_test.go

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ import (
2424
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold"
2525
"github.com/operator-framework/operator-sdk/internal/pkg/scaffold/input"
2626
"github.com/operator-framework/operator-sdk/internal/util/diffutil"
27-
28-
olmregistry "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry"
2927
)
3028

3129
func TestPackageManifest(t *testing.T) {
@@ -70,74 +68,3 @@ const packageManifestExp = `channels:
7068
defaultChannel: stable
7169
packageName: app-operator
7270
`
73-
74-
func TestValidatePackageManifest(t *testing.T) {
75-
channels := []olmregistry.PackageChannel{
76-
{Name: "foo", CurrentCSVName: "bar"},
77-
}
78-
pm := &olmregistry.PackageManifest{
79-
Channels: channels,
80-
DefaultChannelName: "baz",
81-
PackageName: "test-package",
82-
}
83-
84-
cases := []struct {
85-
description string
86-
wantErr bool
87-
errMsg string
88-
operation func(*olmregistry.PackageManifest)
89-
}{
90-
{
91-
"default channel does not exist",
92-
true, "default channel baz does not exist in channels", nil,
93-
},
94-
{
95-
"successful validation",
96-
false, "",
97-
func(pm *olmregistry.PackageManifest) {
98-
pm.DefaultChannelName = pm.Channels[0].Name
99-
},
100-
},
101-
{
102-
"channels are empty",
103-
true, "channels cannot be empty",
104-
func(pm *olmregistry.PackageManifest) {
105-
pm.Channels = nil
106-
},
107-
},
108-
{
109-
"one channel's CSVName is empty",
110-
true, "channel foo currentCSV cannot be empty",
111-
func(pm *olmregistry.PackageManifest) {
112-
pm.Channels = make([]olmregistry.PackageChannel, 1)
113-
copy(pm.Channels, channels)
114-
pm.Channels[0].CurrentCSVName = ""
115-
},
116-
},
117-
{
118-
"duplicate channel name",
119-
true, "duplicate package manifest channel name foo; channel names must be unique",
120-
func(pm *olmregistry.PackageManifest) {
121-
pm.Channels = append(channels, channels...)
122-
},
123-
},
124-
}
125-
126-
for _, c := range cases {
127-
if c.operation != nil {
128-
c.operation(pm)
129-
}
130-
err := validatePackageManifest(pm)
131-
if c.wantErr {
132-
if err == nil {
133-
t.Errorf(`%s: expected error "%s", got none`, c.description, c.errMsg)
134-
} else if err.Error() != c.errMsg {
135-
t.Errorf(`%s: expected error message "%s", got "%s"`, c.description, c.errMsg, err)
136-
}
137-
} else {
138-
if err != nil {
139-
t.Errorf(`%s: expected no error, got error "%s"`, c.description, err)
140-
}
141-
}
142-
}
143-
}

internal/util/k8sutil/k8sutil.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ package k8sutil
1616

1717
import (
1818
"fmt"
19+
"strings"
20+
"unicode"
1921

22+
"github.com/ghodss/yaml"
2023
"k8s.io/client-go/rest"
2124
"k8s.io/client-go/tools/clientcmd"
2225
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
@@ -51,3 +54,48 @@ func GetKubeconfigAndNamespace(configPath string) (*rest.Config, string, error)
5154
}
5255
return kubeconfig, namespace, nil
5356
}
57+
58+
func GetKindfromYAML(yamlData []byte) (string, error) {
59+
var temp struct {
60+
Kind string
61+
}
62+
if err := yaml.Unmarshal(yamlData, &temp); err != nil {
63+
return "", err
64+
}
65+
return temp.Kind, nil
66+
}
67+
68+
// GetDisplayName turns a project dir name in any of {snake, chain, camel}
69+
// cases, hierarchical dot structure, or space-delimited into a
70+
// space-delimited, title'd display name.
71+
// Ex. "another-_AppOperator_againTwiceThrice More"
72+
// -> "Another App Operator Again Twice Thrice More"
73+
func GetDisplayName(name string) string {
74+
for _, sep := range ".-_ " {
75+
splitName := strings.Split(name, string(sep))
76+
for i := 0; i < len(splitName); i++ {
77+
if splitName[i] == "" {
78+
splitName = append(splitName[:i], splitName[i+1:]...)
79+
i--
80+
} else {
81+
splitName[i] = strings.TrimSpace(splitName[i])
82+
}
83+
}
84+
name = strings.Join(splitName, " ")
85+
}
86+
splitName := strings.Split(name, " ")
87+
for i, word := range splitName {
88+
temp := word
89+
o := 0
90+
for j, r := range word {
91+
if unicode.IsUpper(r) {
92+
if j > 0 && !unicode.IsUpper(rune(word[j-1])) {
93+
temp = temp[0:j+o] + " " + temp[j+o:len(temp)]
94+
o++
95+
}
96+
}
97+
}
98+
splitName[i] = temp
99+
}
100+
return strings.TrimSpace(strings.Title(strings.Join(splitName, " ")))
101+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
15+
package k8sutil
16+
17+
import "testing"
18+
19+
func TestGetDisplayName(t *testing.T) {
20+
cases := []struct {
21+
input, wanted string
22+
}{
23+
{"Appoperator", "Appoperator"},
24+
{"appoperator", "Appoperator"},
25+
{"appoperatoR", "Appoperato R"},
26+
{"AppOperator", "App Operator"},
27+
{"appOperator", "App Operator"},
28+
{"app-operator", "App Operator"},
29+
{"app-_operator", "App Operator"},
30+
{"App-operator", "App Operator"},
31+
{"app-_Operator", "App Operator"},
32+
{"app--Operator", "App Operator"},
33+
{"app--_Operator", "App Operator"},
34+
{"APP", "APP"},
35+
{"another-AppOperator_againTwiceThrice More", "Another App Operator Again Twice Thrice More"},
36+
}
37+
38+
for _, c := range cases {
39+
dn := GetDisplayName(c.input)
40+
if dn != c.wanted {
41+
t.Errorf("Wanted %s, got %s", c.wanted, dn)
42+
}
43+
}
44+
}

0 commit comments

Comments
 (0)