Skip to content

Commit 3a29c59

Browse files
authored
set field requirement properly (#2876)
1 parent 10ca2d3 commit 3a29c59

File tree

4 files changed

+88
-13
lines changed

4 files changed

+88
-13
lines changed

tools/openapi2crd/cmd/run.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,23 @@ const (
3636
outputOption = "output"
3737
configOption = "config"
3838
forceOption = "force"
39+
crdsOption = "crds"
3940

40-
readOnly = os.O_RDONLY
41+
crdsDefaultValue = "all"
42+
readOnly = os.O_RDONLY
4143
)
4244

4345
func initConfig() {
4446
viper.AutomaticEnv()
4547
}
4648

49+
type RunnerConfig struct {
50+
Input string
51+
Output string
52+
Overwrite bool
53+
Kinds map[string]struct{}
54+
}
55+
4756
func RunCmd(ctx context.Context) *cobra.Command {
4857
cmd := &cobra.Command{
4958
Use: "openapi2crd SPEC_FILE",
@@ -57,41 +66,59 @@ func RunCmd(ctx context.Context) *cobra.Command {
5766
configPath := viper.GetString(configOption)
5867
outputPath := viper.GetString(outputOption)
5968
forceOverwrite := viper.GetBool(forceOption)
69+
crds := viper.GetString(crdsOption)
70+
71+
c := &RunnerConfig{
72+
Input: configPath,
73+
Output: outputPath,
74+
Overwrite: forceOverwrite,
75+
Kinds: make(map[string]struct{}),
76+
}
77+
78+
if crds != crdsDefaultValue {
79+
kinds := strings.Split(crds, ",")
80+
c.Kinds = make(map[string]struct{}, len(kinds))
81+
for _, kind := range kinds {
82+
c.Kinds[strings.TrimSpace(kind)] = struct{}{}
83+
}
84+
}
6085

6186
fs := afero.NewOsFs()
6287

63-
return runOpenapi2crd(ctx, fs, configPath, outputPath, forceOverwrite)
88+
return runOpenapi2crd(ctx, fs, c)
6489
},
6590
}
6691

6792
cmd.Flags().StringP(outputOption, "o", "", "Path to output file (required)")
6893
_ = cmd.MarkFlagRequired(outputOption)
6994
cmd.Flags().StringP(configOption, "c", "", "Path to the config file (required)")
95+
_ = cmd.MarkFlagRequired(configOption)
7096
cmd.Flags().BoolP(forceOption, "f", false, "Force overwrite the output file if it exists")
97+
cmd.Flags().String(crdsOption, crdsDefaultValue, "One or more Kind names to generate, separated by comma. Use 'all' to generate all CRDs.")
7198
cobra.OnInitialize(initConfig)
7299

73100
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
74101

75102
return cmd
76103
}
77104

78-
func runOpenapi2crd(ctx context.Context, fs afero.Fs, input, output string, overwrite bool) error {
79-
file, err := fs.OpenFile(input, readOnly, 0o644)
105+
func runOpenapi2crd(ctx context.Context, fs afero.Fs, runnerConfig *RunnerConfig) error {
106+
file, err := fs.OpenFile(runnerConfig.Input, readOnly, 0o644)
80107
if err != nil {
81-
return fmt.Errorf("error opening the file %s: %w", input, err)
108+
return fmt.Errorf("error opening the file %s: %w", runnerConfig.Input, err)
82109
}
83110

84111
configData, err := afero.ReadAll(file)
85112
if err != nil {
86-
return fmt.Errorf("error reading the file %s: %w", input, err)
113+
return fmt.Errorf("error reading the file %s: %w", runnerConfig.Input, err)
87114
}
88115

89116
cfg, err := config.Parse(configData)
90117
if err != nil {
91118
return fmt.Errorf("error parsing config: %w", err)
92119
}
93120

94-
fsExporter, err := exporter.New(fs, output, overwrite)
121+
fsExporter, err := exporter.New(fs, runnerConfig.Output, runnerConfig.Overwrite)
95122
if err != nil {
96123
return fmt.Errorf("error creating the exporter: %w", err)
97124
}
@@ -116,6 +143,11 @@ func runOpenapi2crd(ctx context.Context, fs afero.Fs, input, output string, over
116143
atlasLoader := config.NewAtlas(openapiLoader)
117144

118145
for _, crdConfig := range cfg.Spec.CRDConfig {
146+
_, shouldGen := runnerConfig.Kinds[crdConfig.GVK.Kind]
147+
if len(runnerConfig.Kinds) > 0 && !shouldGen {
148+
continue
149+
}
150+
119151
pluginSet, err := plugins.GetPluginSet(pluginSets, crdConfig.PluginSet)
120152
if err != nil {
121153
return fmt.Errorf("error getting plugin set %q: %w", crdConfig.PluginSet, err)

tools/openapi2crd/cmd/run_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,13 @@ func TestRunOpenapi2crd(t *testing.T) {
4747
err = afero.WriteFile(fs, "./testdata/openapi.yaml", []byte(openapiFile()), 0o644)
4848
require.NoError(t, err)
4949

50-
err = runOpenapi2crd(context.Background(), fs, tt.input, tt.output, tt.overwrite)
50+
c := &RunnerConfig{
51+
Input: tt.input,
52+
Output: tt.output,
53+
Overwrite: tt.overwrite,
54+
}
55+
56+
err = runOpenapi2crd(context.Background(), fs, c)
5157
assert.Equal(t, tt.expectedErr, err)
5258
})
5359
}

tools/openapi2crd/pkg/plugins/parameters.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ package plugins
1818
import (
1919
"fmt"
2020

21+
"tools/openapi2crd/pkg/converter"
22+
2123
"github.com/getkin/kin-openapi/openapi3"
2224
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
23-
24-
"tools/openapi2crd/pkg/converter"
2525
)
2626

2727
// Parameters adds parameters from the OpenAPI spec to the CRD schema.
@@ -79,7 +79,10 @@ func (p *Parameters) Process(req *MappingProcessorRequest) error {
7979
},
8080
}
8181
majorVersionSpec.Properties[param.Value.Name] = *props
82-
majorVersionSpec.Required = append(majorVersionSpec.Required, param.Value.Name)
82+
83+
if param.Value.Required {
84+
majorVersionSpec.Required = append(majorVersionSpec.Required, param.Value.Name)
85+
}
8386
}
8487
}
8588
}

tools/openapi2crd/pkg/plugins/parameters_test.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,18 @@ func TestParameterProcess(t *testing.T) {
5656
},
5757
},
5858
},
59+
"test": {
60+
Description: "required parameter for testing purposes",
61+
Type: "object",
62+
XValidations: apiextensions.ValidationRules{
63+
{
64+
Rule: "self == oldSelf",
65+
Message: "test cannot be modified after creation",
66+
},
67+
},
68+
},
5969
},
60-
Required: []string{"projectOwnerId"},
70+
Required: []string{"test"},
6171
},
6272
},
6373
"missing path in OpenAPI spec": {
@@ -132,8 +142,18 @@ func TestParameterProcess(t *testing.T) {
132142
},
133143
},
134144
},
145+
"test": {
146+
Description: "required parameter for testing purposes",
147+
Type: "object",
148+
XValidations: apiextensions.ValidationRules{
149+
{
150+
Rule: "self == oldSelf",
151+
Message: "test cannot be modified after creation",
152+
},
153+
},
154+
},
135155
},
136-
Required: []string{"projectOwnerId"},
156+
Required: []string{"test"},
137157
},
138158
},
139159
}
@@ -203,6 +223,20 @@ func groupMappingRequest(
203223
},
204224
},
205225
},
226+
&openapi3.ParameterRef{
227+
Value: &openapi3.Parameter{
228+
Name: "test",
229+
In: "query",
230+
Description: "required parameter for testing purposes",
231+
Schema: &openapi3.SchemaRef{
232+
Value: &openapi3.Schema{
233+
Type: &openapi3.Types{"boolean"},
234+
Default: false,
235+
},
236+
},
237+
Required: true,
238+
},
239+
},
206240
},
207241
RequestBody: &openapi3.RequestBodyRef{
208242
Value: &openapi3.RequestBody{

0 commit comments

Comments
 (0)