-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
api.go
141 lines (112 loc) · 4.22 KB
/
api.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package v1
import (
"errors"
"fmt"
"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/util"
"sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/declarative/v1/scaffolds"
goPluginV2 "sigs.k8s.io/kubebuilder/v3/pkg/plugins/golang/v2"
)
const (
// kbDeclarativePattern is the sigs.k8s.io/kubebuilder-declarative-pattern version
kbDeclarativePatternForV2 = "v0.0.0-20200522144838-848d48e5b073"
kbDeclarativePatternForV3 = "fe5be9431eae158f86f9de23000a9a2ec06745fc"
)
var _ plugin.CreateAPISubcommand = &createAPISubcommand{}
type createAPISubcommand struct {
config config.Config
resource *resource.Resource
}
func (p *createAPISubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
subcmdMeta.Description = `
Scaffold a Kubernetes API by writing a Resource definition and a Controller.
After the scaffold is written, the dependencies will be updated and
make generate will be run.
`
subcmdMeta.Examples = fmt.Sprintf(` # Create a frigates API with Group: ship, Version: v1beta1 and Kind: Frigate
%[1]s create api --group ship --version v1beta1 --kind Frigate --resource --controller
# Edit the API Scheme
nano api/v1beta1/frigate_types.go
# Edit the Controller Test
nano controllers/frigate/frigate_controller_test.go
# Generate the manifests
make manifests
# Install CRDs into the Kubernetes cluster using kubectl apply
make install
# Regenerate code and run against the Kubernetes cluster configured by ~/.kube/config
make run
`, cliMeta.CommandName)
}
func (p *createAPISubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}
func (p *createAPISubcommand) InjectResource(res *resource.Resource) error {
p.resource = res
if !p.resource.HasAPI() || !p.resource.HasController() {
return plugin.ExitError{
Plugin: pluginName,
Reason: "declarative pattern is only supported when API and controller are scaffolded",
}
}
return nil
}
func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
fmt.Println("updating scaffold with declarative pattern...")
scaffolder := scaffolds.NewAPIScaffolder(p.config, *p.resource)
scaffolder.InjectFS(fs)
err := scaffolder.Scaffold()
if err != nil {
return err
}
// Update Dockerfile
err = updateDockerfile()
if err != nil {
return err
}
// Track the resources following a declarative approach
cfg := pluginConfig{}
if err := p.config.DecodePluginConfig(pluginKey, &cfg); errors.As(err, &config.UnsupportedFieldError{}) {
// Config doesn't support per-plugin configuration, so we can't track them
} else {
// Fail unless they key wasn't found, which just means it is the first resource tracked
if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) {
return err
}
cfg.Resources = append(cfg.Resources, p.resource.GVK)
if err := p.config.EncodePluginConfig(pluginKey, cfg); err != nil {
return err
}
}
// Ensure that we are pinning sigs.k8s.io/kubebuilder-declarative-pattern version
// Just pin an old value for go/v2. It shows fine for now. However, we should improve/change it
// if we see that more rules based on the plugins version are required.
kbDeclarativePattern := kbDeclarativePatternForV3
for _, pluginKey := range p.config.GetPluginChain() {
if pluginKey == plugin.KeyFor(goPluginV2.Plugin{}) {
kbDeclarativePattern = kbDeclarativePatternForV2
break
}
}
err = util.RunCmd("Get declarative pattern", "go", "get",
"sigs.k8s.io/kubebuilder-declarative-pattern@"+kbDeclarativePattern)
if err != nil {
return err
}
return nil
}