Skip to content
This repository has been archived by the owner on Mar 7, 2023. It is now read-only.

Commit

Permalink
feat: use CAPI utils for CAPI requests
Browse files Browse the repository at this point in the history
Updated dependencies to the latest version to align with `capi-utils`
versions.
That lead to several changes in the code:

- No longer using `runtime-client` in the code as it no longer has `runtime.Object` interface
compatibility.
- `capi-utils` manager is now used to query deployed clusters
information.
- `kubernetes` runtime now operates only `Unstructured` Objects.
- Thanks to migration to `Unstructured` `Runtime.List` now returns `[]interface{}` instead of object containing `items` field.

Signed-off-by: Artem Chernyshev <artem.chernyshev@talos-systems.com>
  • Loading branch information
Unix4ever committed Oct 15, 2021
1 parent 5ed5ba2 commit 076fee1
Show file tree
Hide file tree
Showing 18 changed files with 660 additions and 669 deletions.
2 changes: 1 addition & 1 deletion frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default {
if(response.contexts)
contexts.value = response.contexts;
if(response.current) {
if(response.current && !context.current.value) {
currentContext.value = response.current;
context.current.value = {
name: response.current,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ClusterListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default {
onMounted(async () => {
const response = await ResourceService.List({
namespace: item.value.metadata.namespace,
type: "machinelist.v1alpha3.cluster.x-k8s.io",
type: "machines.v1alpha3.cluster.x-k8s.io",
}, {
selectors: [
`cluster.x-k8s.io/cluster-name=${item.value.metadata.name}`
Expand All @@ -143,7 +143,7 @@ export default {
let count = 0;
for (const m of response) {
count += m.items.length;
count += m.length;
}
nodesCount.value = count;
Expand Down
1 change: 0 additions & 1 deletion frontend/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export function changeContext(c: Object) {
context.current.value = c;
}


export function getContext() {
const route = useRoute();

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/views/SidebarNode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ export default {
context: context,
});
for(const message of response) {
services.value = services.value.concat(message["items"]);
for(const items of response) {
services.value = services.value.concat(items);
}
});
Expand Down
31 changes: 12 additions & 19 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ replace (
// forked go-yaml that introduces RawYAML interface, which can be used to populate YAML fields using bytes
// which are then encoded as a valid YAML blocks with proper indentiation
gopkg.in/yaml.v3 => github.com/unix4ever/yaml v0.0.0-20210315173758-8fb30b8e5a5b
// keep older versions of k8s.io packages to keep compatiblity with cluster-api
k8s.io/api v0.21.3 => k8s.io/api v0.20.5
k8s.io/apimachinery v0.21.3 => k8s.io/apimachinery v0.20.5
k8s.io/client-go v0.21.3 => k8s.io/client-go v0.20.5

sigs.k8s.io/cluster-api v0.3.20 => sigs.k8s.io/cluster-api v0.3.9
)

require (
Expand All @@ -24,24 +18,23 @@ require (
github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.4.2
github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0
github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.2.1
github.com/stretchr/testify v1.7.0
github.com/talos-systems/cluster-api-bootstrap-provider-talos v0.2.0
github.com/talos-systems/cluster-api-control-plane-provider-talos v0.1.0
github.com/talos-systems/capi-utils v0.0.0-20211014162503-b018ea29c13a
github.com/talos-systems/grpc-proxy v0.2.0
github.com/talos-systems/sidero v0.3.0
github.com/talos-systems/talos v0.11.0-alpha.2.0.20210721155126-70d2505b7c88
github.com/talos-systems/talos/pkg/machinery v0.0.0-20210715153248-2e463348b26f
go.uber.org/zap v1.18.1
golang.org/x/oauth2 v0.0.0-20210622215436-a8dc77f794b6
github.com/talos-systems/talos/pkg/machinery v0.12.3
go.uber.org/zap v1.19.0
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
google.golang.org/grpc v1.39.0
google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.27.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/api v0.21.3
k8s.io/apiextensions-apiserver v0.19.1
k8s.io/apimachinery v0.21.3
k8s.io/client-go v0.21.3
sigs.k8s.io/cluster-api v0.3.20
sigs.k8s.io/controller-runtime v0.6.3
k8s.io/api v0.22.2
k8s.io/apiextensions-apiserver v0.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
sigs.k8s.io/cluster-api v0.4.3
sigs.k8s.io/controller-runtime v0.9.7
)
300 changes: 109 additions & 191 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/backend/logging/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package logging contains zap logging heplers.
// Package logging contains zap logging helpers.
package logging

import (
Expand Down
228 changes: 228 additions & 0 deletions internal/backend/runtime/kubernetes/capi/proxy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
// this source code form is subject to the terms of the mozilla public
// license, v. 2.0. if a copy of the mpl was not distributed with this
// file, you can obtain one at http://mozilla.org/mpl/2.0/.

// Package capi contains capi util helpers specific to Theila.
package capi

import (
"context"
"fmt"
"strings"

"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// this is a copy from clusterapi, unfortunately these vars are not exported.
const (
minVersion = "v1.16.0"
maxVersion = "v1.22.2"
)

// Proxy custom implementation of clusterapi proxy that allows getting kubeconfig from memory.
type Proxy struct {
config *rest.Config
client client.Client
}

// NewProxy creates new proxy.
func NewProxy(config *rest.Config) *Proxy {
return &Proxy{
config: config,
}
}

// CurrentNamespace implements cluster.Proxy interface.
func (k *Proxy) CurrentNamespace() (string, error) {
return "default", nil
}

// ValidateKubernetesVersion implements cluster.Proxy interface.
func (k *Proxy) ValidateKubernetesVersion() error {
cmp, err := k.compareVersions(minVersion)
if err != nil {
return err
}

if cmp == -1 {
return fmt.Errorf("unsupported management cluster version: minimum required version is %s", minVersion)
}

return nil
}

// ValidateKubernetesMaxVersion implements cluster.Proxy interface.
func (k *Proxy) ValidateKubernetesMaxVersion() error {
cmp, err := k.compareVersions(maxVersion)
if err != nil {
return err
}

if cmp == -1 {
return fmt.Errorf("unsupported management cluster version: maximum required version is %s", maxVersion)
}

return nil
}

// GetConfig returns the config for a kubernetes client.
func (k *Proxy) GetConfig() (*rest.Config, error) {
return k.config, nil
}

// GetContexts implements cluster.Proxy interface.
func (k *Proxy) GetContexts(string) ([]string, error) {
return nil, fmt.Errorf("not implemented")
}

// NewClient implements cluster.Proxy interface.
func (k *Proxy) NewClient() (client.Client, error) {
if k.client != nil {
return k.client, nil
}

var err error

k.client, err = client.New(k.config, client.Options{Scheme: Scheme})
if err != nil {
return nil, err
}

return k.client, nil
}

// ListResources implements cluster.Proxy interface.
func (k *Proxy) ListResources(labels map[string]string, namespaces ...string) ([]unstructured.Unstructured, error) {
cs, err := k.newClientSet()
if err != nil {
return nil, err
}

c, err := k.NewClient()
if err != nil {
return nil, err
}

// Get all the API resources in the cluster.
var resourceList []*metav1.APIResourceList

resourceList, err = cs.Discovery().ServerPreferredResources()

if err != nil {
return nil, err
}

// Select resources with list and delete methods (list is required by this method, delete by the callers of this method)
resourceList = discovery.FilteredBy(discovery.SupportsAllVerbs{Verbs: []string{"list", "delete"}}, resourceList)

var ret []unstructured.Unstructured

discard := map[string]struct{}{
"daemonsets": {},
"deployments": {},
"replicasets": {},
"networkpolicies": {},
"ingresses": {},
}

for _, resourceGroup := range resourceList {
for _, resourceKind := range resourceGroup.APIResources {
// Discard the resourceKind that exists in two api groups (we are excluding one of the two groups arbitrarily).
if _, ok := discard[resourceKind.Name]; resourceGroup.GroupVersion == "extensions/v1beta1" && ok {
continue
}

// List all the object instances of this resourceKind with the given labels
if resourceKind.Namespaced {
for _, namespace := range namespaces {
objList, err := listObjByGVK(c, resourceGroup.GroupVersion, resourceKind.Kind, []client.ListOption{client.MatchingLabels(labels), client.InNamespace(namespace)})
if err != nil {
return nil, err
}

ret = append(ret, objList.Items...)
}
} else {
objList, err := listObjByGVK(c, resourceGroup.GroupVersion, resourceKind.Kind, []client.ListOption{client.MatchingLabels(labels)})
if err != nil {
return nil, err
}

ret = append(ret, objList.Items...)
}
}
}

return ret, nil
}

// GetResourceNames returns the list of resource names which begin with prefix.
func (k *Proxy) GetResourceNames(groupVersion, kind string, options []client.ListOption, prefix string) ([]string, error) {
client, err := k.NewClient()
if err != nil {
return nil, err
}

objList, err := listObjByGVK(client, groupVersion, kind, options)
if err != nil {
return nil, err
}

var comps []string

for _, item := range objList.Items {
name := item.GetName()

if strings.HasPrefix(name, prefix) {
comps = append(comps, name)
}
}

return comps, nil
}

func (k *Proxy) newClientSet() (*kubernetes.Clientset, error) {
return kubernetes.NewForConfig(k.config)
}

func (k *Proxy) compareVersions(ver string) (int, error) {
client, err := discovery.NewDiscoveryClientForConfig(k.config)
if err != nil {
return 0, err
}

version, err := client.ServerVersion()
if err != nil {
return 0, err
}

var v *utilversion.Version

if v, err = utilversion.ParseGeneric(version.String()); err != nil {
return 0, err
}

return v.Compare(ver)
}

func listObjByGVK(c client.Client, groupVersion, kind string, options []client.ListOption) (*unstructured.UnstructuredList, error) {
objList := new(unstructured.UnstructuredList)
objList.SetAPIVersion(groupVersion)
objList.SetKind(kind)

if err := c.List(context.Background(), objList, options...); err != nil {
if !apierrors.IsNotFound(err) {
return nil, errors.Wrapf(err, "failed to list objects for the %q GroupVersionKind", objList.GroupVersionKind())
}
}

return objList, nil
}
31 changes: 31 additions & 0 deletions internal/backend/runtime/kubernetes/capi/scheme.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

package capi

import (
admissionregistration "k8s.io/api/admissionregistration/v1"
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha4"
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1alpha4"
)

// Scheme for CAPI kubernetes client.
var Scheme = runtime.NewScheme()

func init() {
clientgoscheme.AddToScheme(Scheme) //nolint:errcheck
clusterctlv1.AddToScheme(Scheme) //nolint:errcheck
clusterv1.AddToScheme(Scheme) //nolint:errcheck
apiextensionsv1.AddToScheme(Scheme) //nolint:errcheck
apiextensionsv1beta1.AddToScheme(Scheme) //nolint:errcheck
admissionregistration.AddToScheme(Scheme) //nolint:errcheck
admissionregistrationv1beta1.AddToScheme(Scheme) //nolint:errcheck
addonsv1.AddToScheme(Scheme) //nolint:errcheck
}
Loading

0 comments on commit 076fee1

Please sign in to comment.