Skip to content

Commit cce8420

Browse files
committed
remove dependency on controller-runtime
1 parent 6005d29 commit cce8420

File tree

6 files changed

+107
-19
lines changed

6 files changed

+107
-19
lines changed

bootstrap/crds.go

Lines changed: 93 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,23 @@
11
package bootstrap
22

33
import (
4+
"context"
5+
"fmt"
46
"io/fs"
57
"path"
68
"time"
79

10+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
811
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
12+
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
13+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
14+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
15+
"k8s.io/apimachinery/pkg/runtime/schema"
16+
"k8s.io/apimachinery/pkg/util/wait"
917
"k8s.io/apimachinery/pkg/util/yaml"
18+
"k8s.io/client-go/discovery"
1019
"k8s.io/client-go/rest"
11-
"sigs.k8s.io/controller-runtime/pkg/envtest"
20+
"k8s.io/client-go/util/retry"
1221
)
1322

1423
const (
@@ -18,7 +27,7 @@ const (
1827
)
1928

2029
// CRD installs the CRDs in the filesystem into the kube cluster configured by the rest config.
21-
func CRD(restConfig *rest.Config, crdFS fs.ReadDirFS, dir string) error {
30+
func CRD(ctx context.Context, restConfig *rest.Config, crdFS fs.ReadDirFS, dir string) error {
2231
crds := make([]*v1.CustomResourceDefinition, 0)
2332

2433
crdFiles, err := crdFS.ReadDir(dir)
@@ -37,11 +46,87 @@ func CRD(restConfig *rest.Config, crdFS fs.ReadDirFS, dir string) error {
3746
crds = append(crds, &crd)
3847
}
3948

40-
_, err = envtest.InstallCRDs(restConfig, envtest.CRDInstallOptions{
41-
CRDs: crds,
42-
MaxTime: maxCRDInstallTime,
43-
PollInterval: crdInstallPollInterval,
44-
CleanUpAfterUse: false,
45-
})
49+
if err := createCRDs(ctx, restConfig, crds); err != nil {
50+
return err
51+
}
52+
53+
if err := waitForDiscovery(ctx, restConfig, crds); err != nil {
54+
return err
55+
}
56+
4657
return err
4758
}
59+
60+
// createCRDs creates (or updates) CRDs in the cluster
61+
func createCRDs(ctx context.Context, config *rest.Config, crds []*apiextensionsv1.CustomResourceDefinition) error {
62+
c, err := clientset.NewForConfig(config)
63+
if err != nil {
64+
return err
65+
}
66+
crdClient := c.ApiextensionsV1().CustomResourceDefinitions()
67+
for _, crd := range crds {
68+
crd := crd
69+
_, err = crdClient.Get(ctx, crd.GetName(), metav1.GetOptions{})
70+
if k8serrors.IsNotFound(err) {
71+
if _, err := crdClient.Create(ctx, crd, metav1.CreateOptions{}); err != nil {
72+
return fmt.Errorf("unable to create CRD %q: %w", crd.Name, err)
73+
}
74+
continue
75+
}
76+
if err != nil {
77+
return fmt.Errorf("failed when fetching CRD %q: %w", crd.Name, err)
78+
}
79+
80+
if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
81+
got, err := crdClient.Get(ctx, crd.Name, metav1.GetOptions{})
82+
if err != nil {
83+
return err
84+
}
85+
crd.SetResourceVersion(got.GetResourceVersion())
86+
_, err = crdClient.Update(ctx, crd, metav1.UpdateOptions{})
87+
return err
88+
}); err != nil {
89+
return err
90+
}
91+
}
92+
return nil
93+
}
94+
95+
func waitForDiscovery(ctx context.Context, config *rest.Config, crds []*apiextensionsv1.CustomResourceDefinition) error {
96+
gvrs := map[schema.GroupVersionResource]struct{}{}
97+
for _, crd := range crds {
98+
for _, version := range crd.Spec.Versions {
99+
if !version.Served {
100+
continue
101+
}
102+
gvrs[schema.GroupVersionResource{
103+
Group: crd.Spec.Group,
104+
Version: version.Name,
105+
Resource: crd.Spec.Names.Plural,
106+
}] = struct{}{}
107+
}
108+
}
109+
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
110+
if err != nil {
111+
return err
112+
}
113+
114+
return wait.PollUntilContextTimeout(ctx, crdInstallPollInterval, maxCRDInstallTime, true, func(ctx context.Context) (done bool, err error) {
115+
_, serverGVRs, err := discoveryClient.ServerGroupsAndResources()
116+
if err != nil {
117+
return false, nil
118+
}
119+
120+
for _, gv := range serverGVRs {
121+
for _, r := range gv.APIResources {
122+
delete(gvrs, schema.GroupVersionResource{
123+
Group: r.Group,
124+
Version: r.Version,
125+
Resource: r.Name,
126+
})
127+
}
128+
}
129+
130+
return len(gvrs) == 0, nil
131+
})
132+
}

bootstrap/crds_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package bootstrap
22

33
import (
4+
"context"
45
"embed"
56

67
"k8s.io/client-go/rest"
@@ -10,6 +11,6 @@ import (
1011
var crdFS embed.FS
1112

1213
func ExampleCRD() {
13-
_ = CRD(&rest.Config{}, crdFS, "example")
14+
_ = CRD(context.Background(), &rest.Config{}, crdFS, "example")
1415
// Output:
1516
}

bootstrap/resource.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ package bootstrap
1515
import (
1616
"bytes"
1717
"context"
18+
"encoding/json"
1819
"errors"
1920
"io"
2021
"os"
@@ -29,7 +30,6 @@ import (
2930
"k8s.io/apimachinery/pkg/util/yaml"
3031
"k8s.io/client-go/dynamic"
3132
"k8s.io/utils/pointer"
32-
"sigs.k8s.io/controller-runtime/pkg/client"
3333
)
3434

3535
// KubeResourceObject is satisfied by any standard kube object.
@@ -78,7 +78,7 @@ func ResourceFromFile[O KubeResourceObject](ctx context.Context, fieldManager st
7878
return hash, err
7979
}
8080

81-
data, err := client.Apply.Data(objectDef)
81+
data, err := json.Marshal(objectDef)
8282
if err != nil {
8383
return hash, err
8484
}

go.mod

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ require (
2222
k8s.io/klog/v2 v2.90.1
2323
k8s.io/utils v0.0.0-20230209194617-a36077c30491
2424
mvdan.cc/gofumpt v0.3.1
25-
sigs.k8s.io/controller-runtime v0.14.1
2625
)
2726

2827
require (
@@ -36,7 +35,6 @@ require (
3635
github.com/coreos/go-systemd/v22 v22.4.0 // indirect
3736
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
3837
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
39-
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
4038
github.com/felixge/httpsnoop v1.0.3 // indirect
4139
github.com/go-logr/stdr v1.2.2 // indirect
4240
github.com/go-openapi/jsonpointer v0.19.6 // indirect

go.sum

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.
9696
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
9797
github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84=
9898
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
99-
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
100-
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
10199
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
102100
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
103101
github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns=
@@ -221,7 +219,6 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
221219
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
222220
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
223221
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
224-
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
225222
github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ=
226223
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
227224
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@@ -593,7 +590,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
593590
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
594591
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
595592
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
596-
gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY=
597593
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
598594
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
599595
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -744,8 +740,6 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
744740
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
745741
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2 h1:trsWhjU5jZrx6UvFu4WzQDrN7Pga4a7Qg+zcfcj64PA=
746742
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.1.2/go.mod h1:+qG7ISXqCDVVcyO8hLn12AKVYYUjM7ftlqsqmrhMZE0=
747-
sigs.k8s.io/controller-runtime v0.14.1 h1:vThDes9pzg0Y+UbCPY3Wj34CGIYPgdmspPm2GIpxpzM=
748-
sigs.k8s.io/controller-runtime v0.14.1/go.mod h1:GaRkrY8a7UZF0kqFFbUKG7n9ICiTY5T55P1RiE3UZlU=
749743
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
750744
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
751745
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=

typed/typedlister.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,13 @@ func UnstructuredObjToTypedObj[K runtime.Object](obj runtime.Object) (K, error)
100100
}
101101
return *typedObj, nil
102102
}
103+
104+
// TypedObjToUnstructuredObj is a helper that converts a typed object
105+
// to unstructured.
106+
func TypedObjToUnstructuredObj(typedObj runtime.Object) (*unstructured.Unstructured, error) {
107+
object, err := runtime.DefaultUnstructuredConverter.ToUnstructured(typedObj)
108+
if err != nil {
109+
return nil, err
110+
}
111+
return &unstructured.Unstructured{Object: object}, nil
112+
}

0 commit comments

Comments
 (0)