Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource conversion, one solo-kit.json per project #214

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ required = ["k8s.io/code-generator/cmd/client-gen"]
name = "k8s.io/gengo"
unused-packages = false

[[override]]
name = "gopkg.in/fsnotify.v1"
source = "https://github.com/fsnotify/fsnotify.git"

[[constraint]]
version = "1.1.1"
name = "github.com/gogo/protobuf"
Expand Down
89 changes: 48 additions & 41 deletions api/external/kubernetes/solo-kit.json
Original file line number Diff line number Diff line change
@@ -1,44 +1,51 @@
{
"title": "solo-kit",
"name": "kubernetes.solo.io",
"version": "kubernetes",
"go_package": "github.com/solo-io/solo-kit/pkg/api/v1/resources/common/kubernetes",
"custom_resources": [
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/pod",
"type": "Pod",
"plural_name": "pods",
"short_name": "p"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/namespace",
"type": "KubeNamespace",
"plural_name": "kubenamespaces",
"short_name": "kn"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/configmap",
"type": "ConfigMap",
"plural_name": "configmaps",
"short_name": "cm"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/service",
"type": "Service",
"plural_name": "services",
"short_name": "svc"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/deployment",
"type": "Deployment",
"plural_name": "deployments",
"short_name": "dp "
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/customresourcedefinition",
"type": "CustomResourceDefinition",
"plural_name": "customresourcedefinition",
"short_name": "crd "
}
]
"api_group": {
"name": "kubernetes.solo.io",
"resource_group_go_package": "github.com/solo-io/solo-kit/api/external/kubernetes/group",
"version_configs": [
{
"version": "kubernetes",
"go_package": "github.com/solo-io/solo-kit/pkg/api/v1/resources/common/kubernetes",
"custom_resources": [
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/pod",
"type": "Pod",
"plural_name": "pods",
"short_name": "p"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/namespace",
"type": "KubeNamespace",
"plural_name": "kubenamespaces",
"short_name": "kn"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/configmap",
"type": "ConfigMap",
"plural_name": "configmaps",
"short_name": "cm"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/service",
"type": "Service",
"plural_name": "services",
"short_name": "svc"
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/deployment",
"type": "Deployment",
"plural_name": "deployments",
"short_name": "dp "
},
{
"package": "github.com/solo-io/solo-kit/api/external/kubernetes/customresourcedefinition",
"type": "CustomResourceDefinition",
"plural_name": "customresourcedefinition",
"short_name": "crd "
}
]
}
]
}
}
37 changes: 22 additions & 15 deletions api/multicluster/v1/solo-kit.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
{
"title": "Solo-Kit Multicluster Manager",
"name": "multicluster.solo.io",
"version": "v1",
"go_package": "github.com/solo-io/solo-kit/pkg/multicluster/v1",
"custom_resources": [
{
"package": "github.com/solo-io/solo-kit/api/multicluster/v1",
"type": "KubeConfig",
"plural_name": "kubeconfigs",
"short_name": "kc"
}
],
"resource_groups": {
"kubeconfigs.multicluster.solo.io": [
"api_group": {
"name": "multicluster.solo.io",
"resource_group_go_package": "github.com/solo-io/solo-kit/pkg/multicluster/group",
"resource_groups": {
"kubeconfigs.multicluster.solo.io": [
{
"name": "KubeConfig",
"package": "github.com/solo-io/solo-kit/api/multicluster/v1"
}
]
},
"version_configs": [
{
"name": "KubeConfig",
"package": "github.com/solo-io/solo-kit/api/multicluster/v1"
"version": "v1",
"go_package": "github.com/solo-io/solo-kit/pkg/multicluster/v1",
"custom_resources": [
{
"package": "github.com/solo-io/solo-kit/api/multicluster/v1",
"type": "KubeConfig",
"plural_name": "kubeconfigs",
"short_name": "kc"
}
]
}
]
}
Expand Down
7 changes: 7 additions & 0 deletions changelog/v0.12.0/conversions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
changelog:
- type: NEW_FEATURE
description: Generate converters for multi-version resources.
issueLink: https://github.com/solo-io/solo-kit/issues/215
- type: BREAKING_CHANGE
description: Redefine solo-kit project concept to better support multi-version resources.
issueLink: https://github.com/solo-io/solo-kit/issues/215
55 changes: 31 additions & 24 deletions pkg/api/v1/clients/kube/crd/crd.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
package crd

import (
"fmt"
"log"
"sync"

"github.com/solo-io/go-utils/errors"
"github.com/solo-io/solo-kit/pkg/api/v1/clients/kube/crd/client/clientset/versioned/scheme"
v1 "github.com/solo-io/solo-kit/pkg/api/v1/clients/kube/crd/solo.io/v1"
"github.com/solo-io/solo-kit/pkg/api/v1/resources"
"github.com/solo-io/solo-kit/pkg/utils/protoutils"
apiexts "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)

// TODO(ilackarms): evaluate this fix for concurrent map access in k8s.io/apimachinery/pkg/runtime.SchemaBuider
var registerLock sync.Mutex
var (
registerLock sync.Mutex

VersionNotFoundError = func(version string) error {
return errors.Errorf("could not find version %v", version)
}
)

type Converter interface {
Convert(src SoloKitCrd, dst SoloKitCrd) error
}

type SoloKitCrd interface {
runtime.Object
resources.Resource
}

type CrdMeta struct {
Plural string
Expand All @@ -28,7 +42,7 @@ type CrdMeta struct {

type Version struct {
Version string
Type runtime.Object
Type SoloKitCrd
}

type Crd struct {
Expand All @@ -41,14 +55,23 @@ type MultiVersionCrd struct {
Versions []Version
}

func (m *MultiVersionCrd) GetVersion(requested string) (*Version, error) {
for _, version := range m.Versions {
if version.Version == requested {
return &version, nil
}
}
return nil, VersionNotFoundError(requested)
}

func NewCrd(
plural string,
group string,
version string,
kindName string,
shortName string,
clusterScoped bool,
objType runtime.Object) Crd {
objType SoloKitCrd) Crd {
c := Crd{
CrdMeta: CrdMeta{
Plural: plural,
Expand All @@ -73,25 +96,9 @@ func (d Crd) Register(apiexts apiexts.Interface) error {
}

func (d Crd) KubeResource(resource resources.InputResource) *v1.Resource {
data, err := protoutils.MarshalMap(resource)
if err != nil {
panic(fmt.Sprintf("internal error: failed to marshal resource to map: %v", err))
}
delete(data, "metadata")
delete(data, "status")
spec := v1.Spec(data)
return &v1.Resource{
TypeMeta: d.TypeMeta(),
ObjectMeta: metav1.ObjectMeta{
Namespace: resource.GetMetadata().Namespace,
Name: resource.GetMetadata().Name,
ResourceVersion: resource.GetMetadata().ResourceVersion,
Labels: resource.GetMetadata().Labels,
Annotations: resource.GetMetadata().Annotations,
},
Status: resource.GetStatus(),
Spec: &spec,
}
res := KubeResource(resource)
res.TypeMeta = d.TypeMeta()
return res
}

func (d CrdMeta) FullName() string {
Expand Down
33 changes: 33 additions & 0 deletions pkg/api/v1/clients/kube/crd/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import (
"github.com/solo-io/go-utils/errors"
"github.com/solo-io/go-utils/kubeutils"
"github.com/solo-io/go-utils/versionutils/kubeapi"
v1 "github.com/solo-io/solo-kit/pkg/api/v1/clients/kube/crd/solo.io/v1"
"github.com/solo-io/solo-kit/pkg/api/v1/resources"
"github.com/solo-io/solo-kit/pkg/utils/protoutils"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiexts "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand Down Expand Up @@ -48,6 +51,10 @@ func AddCrd(resource Crd) error {
return getRegistry().addCrd(resource)
}

func GetMultiVersionCrd(gk schema.GroupKind) (MultiVersionCrd, error) {
return getRegistry().getMultiVersionCrd(gk)
}

func (r *crdRegistry) addCrd(resource Crd) error {
r.mu.Lock()
defer r.mu.Unlock()
Expand Down Expand Up @@ -167,3 +174,29 @@ func (r crdRegistry) getKubeCrd(crd MultiVersionCrd, gvk schema.GroupVersionKind
},
}, nil
}

func KubeResource(resource resources.Resource) *v1.Resource {
data, err := protoutils.MarshalMap(resource)
if err != nil {
panic(fmt.Sprintf("internal error: failed to marshal resource to map: %v", err))
}
delete(data, "metadata")
delete(data, "status")
spec := v1.Spec(data)
res := &v1.Resource{
ObjectMeta: metav1.ObjectMeta{
Namespace: resource.GetMetadata().Namespace,
Name: resource.GetMetadata().Name,
ResourceVersion: resource.GetMetadata().ResourceVersion,
Labels: resource.GetMetadata().Labels,
Annotations: resource.GetMetadata().Annotations,
},
Spec: &spec,
}

if withStatus, ok := resource.(resources.InputResource); ok {
res.Status = withStatus.GetStatus()
}

return res
}
17 changes: 17 additions & 0 deletions pkg/api/v1/clients/kube/crd/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package crd

import (
"github.com/solo-io/solo-kit/pkg/utils/protoutils"
)

func Copy(src, dst SoloKitCrd) error {
srcBytes, err := protoutils.MarshalBytes(src)
if err != nil {
return err
}
err = protoutils.UnmarshalBytes(srcBytes, dst)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

if err := protoutils.UnmarshalBytes(srcBytes, dst); err != nil {
	return err
}

if err != nil {
return err
}
return nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we doing this copy? there's a resources.Clone function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The copy needs to happen in place onto dst -- clone returns a new object

}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading