Import kube package(cue) by GroupVersion (#1309)

* package upgrade

* package import

* Classified by groupversion

* fix test cases

* add test cases

* check diff

* lint code

* fix test

* add pacakge reference

* VersionKind

* package upgrade

package import

Classified by groupversion

fix test cases

add test cases

check diff

lint code

fix test

add pacakge reference

VersionKind

fix ci
This commit is contained in:
Jian.Li
2021-03-28 18:08:31 +08:00
committed by GitHub
parent aa548ab3d4
commit cfabcee181
6 changed files with 425 additions and 160 deletions
+1 -1
View File
@@ -277,7 +277,7 @@ kustomize:
ifeq (, $(shell kustomize version | grep $(KUSTOMIZE_VERSION)))
@{ \
set -e ;\
echo 'installing kustomize-v$(KUSTOMIZE_VERSION)' ;\
echo 'installing kustomize-v$(KUSTOMIZE_VERSION) into $(GOBIN)' ;\
curl -s https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh | bash -s $(KUSTOMIZE_VERSION) $(GOBIN);\
echo 'Install succeed' ;\
}
@@ -110,6 +110,8 @@ func TestMakeHTTPRequest(t *testing.T) {
},
}
for testName, tt := range tests {
// deep copy it before going to goroutine
tt := tt
t.Run(testName, func(t *testing.T) {
// generate a test server so we can capture and inspect the request
testServer := NewMock(tt.httpParameter.method, tt.httpParameter.statusCode, tt.httpParameter.body)
@@ -1480,8 +1480,11 @@ spec:
name: deployments.apps
extension:
template: |
import "kube/apps/v1"
output: v1.#Deployment & {
import (
"k8s.io/apps/v1"
appsv1 "kube/apps/v1"
)
output: v1.#Deployment & appsv1.#Deployment & {
metadata: {
annotations: {
if context["config"] != _|_ {
@@ -1539,8 +1542,8 @@ spec:
cue:
template: |
import (
kubev1 "kube/v1"
network "kube/networking.k8s.io/v1beta1"
kubev1 "k8s.io/core/v1"
network "k8s.io/networking/v1beta1"
)
parameter: {
+166 -57
View File
@@ -19,6 +19,7 @@ package definition
import (
"context"
"fmt"
"path/filepath"
"strings"
"sync"
"time"
@@ -36,14 +37,28 @@ import (
"k8s.io/client-go/rest"
)
const (
// BuiltinPackageDomain Specify the domain of the built-in package
BuiltinPackageDomain = "kube"
// K8sResourcePrefix Indicates that the definition comes from kubernetes
K8sResourcePrefix = "io_k8s_api_"
)
// PackageDiscover defines the inner CUE packages loaded from K8s cluster
type PackageDiscover struct {
velaBuiltinPackages []*build.Instance
pkgKinds map[string][]string
pkgKinds map[string][]VersionKind
mutex sync.RWMutex
client *rest.RESTClient
}
// VersionKind contains the resource metadata and reference name
type VersionKind struct {
DefinitionName string
APIVersion string
Kind string
}
// NewPackageDiscover will create a PackageDiscover client with the K8s config file.
func NewPackageDiscover(config *rest.Config) (*PackageDiscover, error) {
client, err := getClusterOpenAPIClient(config)
@@ -52,7 +67,7 @@ func NewPackageDiscover(config *rest.Config) (*PackageDiscover, error) {
}
pd := &PackageDiscover{
client: client,
pkgKinds: make(map[string][]string),
pkgKinds: make(map[string][]VersionKind),
}
if err = pd.RefreshKubePackagesFromCluster(); err != nil {
return nil, err
@@ -67,6 +82,13 @@ func (pd *PackageDiscover) ImportBuiltinPackagesFor(bi *build.Instance) {
bi.Imports = append(bi.Imports, pd.velaBuiltinPackages...)
}
// ListPackageKinds list packages and their kinds
func (pd *PackageDiscover) ListPackageKinds() map[string][]VersionKind {
pd.mutex.RLock()
defer pd.mutex.RUnlock()
return pd.pkgKinds
}
// RefreshKubePackagesFromCluster will use K8s client to load/refresh all K8s open API as a reference kube package using in template
func (pd *PackageDiscover) RefreshKubePackagesFromCluster() error {
body, err := pd.client.Get().AbsPath("/openapi/v2").Do(context.Background()).Raw()
@@ -78,13 +100,14 @@ func (pd *PackageDiscover) RefreshKubePackagesFromCluster() error {
// Exist checks if the GVK exists in the built-in packages
func (pd *PackageDiscover) Exist(gvk metav1.GroupVersionKind) bool {
dgvk := convert2DGVK(gvk)
// package name equals to importPath
importPath := genPackageName(gvk.Group, gvk.Version)
importPath := genStandardPkgName(dgvk)
pd.mutex.RLock()
defer pd.mutex.RUnlock()
pkgKinds := pd.pkgKinds[importPath]
for _, k := range pkgKinds {
if k == gvk.Kind {
for _, v := range pkgKinds {
if v.Kind == dgvk.Kind {
return true
}
}
@@ -92,7 +115,7 @@ func (pd *PackageDiscover) Exist(gvk metav1.GroupVersionKind) bool {
}
// mount will mount the new parsed package into PackageDiscover built-in packages
func (pd *PackageDiscover) mount(pkg *pkgInstance, pkgKinds []string) {
func (pd *PackageDiscover) mount(pkg *pkgInstance, pkgKinds []VersionKind) {
pd.mutex.Lock()
defer pd.mutex.Unlock()
for i, p := range pd.velaBuiltinPackages {
@@ -111,7 +134,7 @@ func (pd *PackageDiscover) addKubeCUEPackagesFromCluster(apiSchema string) error
if err != nil {
return err
}
kinds := map[string]metav1.GroupVersionKind{}
dgvkMapper := make(map[string]domainGroupVersionKind)
pathValue := oaInst.Value().Lookup("paths")
if pathValue.Exists() {
if st, err := pathValue.Struct(); err == nil {
@@ -120,8 +143,8 @@ func (pd *PackageDiscover) addKubeCUEPackagesFromCluster(apiSchema string) error
gvk := iter.Value().Lookup("post",
"x-kubernetes-group-version-kind")
if gvk.Exists() {
if v, err := getGVK(gvk); err == nil {
kinds["#"+v.Kind] = v
if v, err := getDGVK(gvk); err == nil {
dgvkMapper[v.reverseString()] = v
}
}
}
@@ -129,55 +152,75 @@ func (pd *PackageDiscover) addKubeCUEPackagesFromCluster(apiSchema string) error
}
oaFile, err := jsonschema.Extract(oaInst, &jsonschema.Config{
Root: "#/definitions",
Map: openAPIMapping,
Map: openAPIMapping(dgvkMapper),
})
if err != nil {
return err
}
kubePkg := newPackage("kube")
kubePkg.processOpenAPIFile(oaFile)
if err := kubePkg.AddSyntax(oaFile); err != nil {
return err
}
packages := make(map[string]*pkgInstance)
groupKinds := make(map[string][]string)
groupKinds := make(map[string][]VersionKind)
for k, v := range kinds {
apiVersion := v.Version
if v.Group != "" {
apiVersion = v.Group + "/" + apiVersion
}
def := fmt.Sprintf(`%s: {
for k := range dgvkMapper {
v := dgvkMapper[k]
apiVersion := v.APIVersion
def := fmt.Sprintf(`
import "kube"
#%s: kube.%s & {
kind: "%s"
apiVersion: "%s",
}`, k, v.Kind, apiVersion)
pkgName := genPackageName(v.Group, v.Version)
pkg, ok := packages[pkgName]
if !ok {
pkg = newPackage(pkgName)
}`, v.Kind, k, v.Kind, apiVersion)
pkgBuild := func(pkgName string) error {
pkg, ok := packages[pkgName]
if !ok {
pkg = newPackage(pkgName)
pkg.Imports = []*build.Instance{kubePkg.Instance}
}
mykinds := groupKinds[pkgName]
mykinds = append(mykinds, VersionKind{
APIVersion: v.APIVersion,
Kind: v.Kind,
DefinitionName: "#" + v.Kind,
})
if err := pkg.AddFile(v.reverseString(), def); err != nil {
return err
}
packages[pkgName] = pkg
groupKinds[pkgName] = mykinds
return nil
}
mykinds := groupKinds[pkgName]
mykinds = append(mykinds, v.Kind)
if err := pkg.AddFile(k, def); err != nil {
if err := pkgBuild(genStandardPkgName(v)); err != nil {
return err
}
if err := pkgBuild(genOpenPkgName(v)); err != nil {
return err
}
packages[pkgName] = pkg
groupKinds[pkgName] = mykinds
}
for name, pkg := range packages {
pkg.processOpenAPIFile(oaFile)
if err = pkg.AddSyntax(oaFile); err != nil {
return err
}
pd.mount(pkg, groupKinds[name])
}
return nil
}
func genPackageName(group, version string) string {
res := []string{"kube"}
if group != "" {
res = append(res, group)
func genOpenPkgName(v domainGroupVersionKind) string {
return BuiltinPackageDomain + "/" + v.APIVersion
}
func genStandardPkgName(v domainGroupVersionKind) string {
res := []string{v.Group, v.Version}
if v.Domain != "" {
res = []string{v.Domain, v.Group, v.Version}
}
// version should never be empty
res = append(res, version)
return strings.Join(res, "/")
}
@@ -207,18 +250,56 @@ func getClusterOpenAPIClient(config *rest.Config) (*rest.RESTClient, error) {
return rest.UnversionedRESTClientFor(&copyConfig)
}
func openAPIMapping(pos token.Pos, a []string) ([]ast.Label, error) {
if len(a) < 2 {
return nil, errors.New("openAPIMapping format invalid")
func openAPIMapping(dgvkMapper map[string]domainGroupVersionKind) func(pos token.Pos, a []string) ([]ast.Label, error) {
return func(pos token.Pos, a []string) ([]ast.Label, error) {
if len(a) < 2 {
return nil, errors.New("openAPIMapping format invalid")
}
name := strings.ReplaceAll(a[1], ".", "_")
if _, ok := dgvkMapper[name]; !ok && strings.HasPrefix(name, K8sResourcePrefix) {
trimName := strings.TrimPrefix(name, K8sResourcePrefix)
if v, ok := dgvkMapper[trimName]; ok {
v.Domain = "k8s.io"
dgvkMapper[name] = v
delete(dgvkMapper, trimName)
}
}
if strings.HasSuffix(a[1], ".JSONSchemaProps") && pos != token.NoPos {
return []ast.Label{ast.NewIdent("_")}, nil
}
return []ast.Label{ast.NewIdent(name)}, nil
}
spl := strings.Split(a[1], ".")
name := spl[len(spl)-1]
}
if name == "JSONSchemaProps" && pos != token.NoPos {
return []ast.Label{ast.NewIdent("_")}, nil
type domainGroupVersionKind struct {
Domain string
Group string
Version string
Kind string
APIVersion string
}
func (dgvk domainGroupVersionKind) reverseString() string {
var s = []string{dgvk.Kind, dgvk.Version}
s = append(s, strings.Split(dgvk.Group, ".")...)
domain := dgvk.Domain
if domain == "k8s.io" {
domain = "api.k8s.io"
}
return []ast.Label{ast.NewIdent("#" + name)}, nil
if domain != "" {
s = append(s, strings.Split(domain, ".")...)
}
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return strings.Join(s, "_")
}
type pkgInstance struct {
@@ -228,7 +309,7 @@ type pkgInstance struct {
func newPackage(name string) *pkgInstance {
return &pkgInstance{
&build.Instance{
PkgName: name,
PkgName: filepath.Base(name),
ImportPath: name,
},
}
@@ -264,17 +345,45 @@ func (pkg *pkgInstance) processOpenAPIFile(f *ast.File) {
}
}
func getGVK(v cue.Value) (metav1.GroupVersionKind, error) {
ret := metav1.GroupVersionKind{}
var err error
ret.Group, err = v.Lookup("group").String()
func getDGVK(v cue.Value) (ret domainGroupVersionKind, err error) {
gvk := metav1.GroupVersionKind{}
gvk.Group, err = v.Lookup("group").String()
if err != nil {
return ret, err
return
}
ret.Version, err = v.Lookup("version").String()
gvk.Version, err = v.Lookup("version").String()
if err != nil {
return ret, err
return
}
ret.Kind, err = v.Lookup("kind").String()
return ret, err
gvk.Kind, err = v.Lookup("kind").String()
if err != nil {
return
}
ret = convert2DGVK(gvk)
return
}
func convert2DGVK(gvk metav1.GroupVersionKind) domainGroupVersionKind {
ret := domainGroupVersionKind{
Version: gvk.Version,
Kind: gvk.Kind,
APIVersion: gvk.Version,
}
if gvk.Group == "" {
ret.Group = "core"
ret.Domain = "k8s.io"
} else {
ret.APIVersion = gvk.Group + "/" + ret.APIVersion
sv := strings.Split(gvk.Group, ".")
// Domain must contain dot
if len(sv) > 2 {
ret.Domain = strings.Join(sv[1:], ".")
ret.Group = sv[0]
} else {
ret.Group = gvk.Group
}
}
return ret
}
+56 -22
View File
@@ -20,11 +20,12 @@ import (
"context"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"cuelang.org/go/cue"
"cuelang.org/go/cue/build"
"github.com/google/go-cmp/cmp"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -38,17 +39,17 @@ import (
var _ = Describe("Package discovery resources for definition from K8s APIServer", func() {
PIt("discovery built-in k8s resource", func() {
It("discovery built-in k8s resource", func() {
By("test ingress in kube package")
bi := build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
err := bi.AddFile("-", `
import (
network "kube/networking.k8s.io/v1beta1"
network "k8s.io/networking/v1beta1"
kube "kube/networking.k8s.io/v1beta1"
)
output: network.#Ingress
output: network.#Ingress & kube.#Ingress
output: {
apiVersion: "networking.k8s.io/v1beta1"
kind: "Ingress"
@@ -102,16 +103,46 @@ parameter: {
"servicePort": int64(80),
}}}}}}}},
})).Should(BeEquivalentTo(""))
By("test Invalid Import path")
bi = build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import (
"k8s.io/networking/v1"
kube "kube/networking.k8s.io/v1"
)
output: v1.#Deployment & kube.#Deployment
output: {
metadata: {
"name": parameter.name
}
spec: template: spec: {
containers: [{
name:"invalid-path",
image: parameter.image
}]
}
}
parameter: {
name: "myapp"
image: "nginx"
}`)
inst, err = r.Build(bi)
Expect(err).Should(BeNil())
_, err = model.NewBase(inst.Lookup("output"))
Expect(err).ShouldNot(BeNil())
Expect(err.Error()).Should(Equal("_|_ // undefined field \"#Deployment\""))
By("test Deployment in kube package")
bi = build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import (
apps "kube/apps/v1"
apps "k8s.io/apps/v1"
kube "kube/apps/v1"
)
output: apps.#Deployment
output: apps.#Deployment & kube.#Deployment
output: {
metadata: {
"name": parameter.name
@@ -123,7 +154,6 @@ output: {
}]
}
}
parameter: {
name: "myapp"
image: "nginx"
@@ -152,16 +182,17 @@ parameter: {
bi = build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import ("kube/v1")
output: v1.#Secret
import (
"k8s.io/core/v1"
kube "kube/v1"
)
output: v1.#Secret & kube.#Secret
output: {
metadata: {
"name": parameter.name
}
type:"kubevela"
}
parameter: {
name: "myapp"
}`)
@@ -181,16 +212,17 @@ parameter: {
bi = build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import ("kube/v1")
output: v1.#Service
import (
"k8s.io/core/v1"
kube "kube/v1"
)
output: v1.#Service & kube.#Service
output: {
metadata: {
"name": parameter.name
}
spec: type: "ClusterIP",
}
parameter: {
name: "myapp"
}`)
@@ -274,10 +306,12 @@ parameter: {
}
bi = build.NewContext().NewInstance("", nil)
pd.ImportBuiltinPackagesFor(bi)
if err = bi.AddFile("-", `
import ("kube/example.com/v1")
output: v1.#Foo
if err := bi.AddFile("-", `
import (
ev1 "example.com/v1"
kv1 "kube/example.com/v1"
)
output: ev1.#Foo & kv1.#Foo
output: {
spec: key: "test1"
status: key: "test2"
+193 -76
View File
@@ -24,6 +24,7 @@ import (
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/parser"
"cuelang.org/go/cue/token"
"github.com/google/go-cmp/cmp"
"gotest.tools/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,7 +38,7 @@ func TestPackage(t *testing.T) {
"paths...": {
"post":{
"x-kubernetes-group-version-kind": {
"group": "test.io",
"group": "apps.test.io",
"kind": "Bucket",
"version": "v1"
}
@@ -45,7 +46,7 @@ func TestPackage(t *testing.T) {
}
},
"definitions":{
"Bucket":{
"io.test.apps.v1.Bucket":{
"properties":{
"apiVersion": {"type": "string"}
"kind": {"type": "string"}
@@ -330,12 +331,85 @@ func TestPackage(t *testing.T) {
}
}
`
mypd := &PackageDiscover{pkgKinds: make(map[string][]string)}
mypd := &PackageDiscover{pkgKinds: make(map[string][]VersionKind)}
mypd.addKubeCUEPackagesFromCluster(openAPISchema)
expectPkgKinds := map[string][]VersionKind{
"test.io/apps/v1": []VersionKind{{
DefinitionName: "#Bucket",
APIVersion: "apps.test.io/v1",
Kind: "Bucket",
}},
"kube/apps.test.io/v1": []VersionKind{{
DefinitionName: "#Bucket",
APIVersion: "apps.test.io/v1",
Kind: "Bucket",
}},
}
assert.Equal(t, cmp.Diff(mypd.ListPackageKinds(), expectPkgKinds), "")
exceptObj := `output: close({
kind: "Bucket"
apiVersion: "apps.test.io/v1"
type: "alicloud_oss_bucket"
acl: "public-read-write" | "public-read" | *"private"
dataRedundancyType?: "ZRS" | *"LRS"
dataSourceRef?: {
dsPath: string
}
importRef?: {
importKey: string
}
output: {
{[!~"^(bucketName|extranetEndpoint|intranetEndpoint|masterUserId)$"]: {
outRef: string
} | {
// Example: demoVpc.vpcId
valueRef: string
}}
bucketName: {
outRef: "self.name"
}
extranetEndpoint: {
outRef: "self.state.extranetEndpoint"
}
intranetEndpoint: {
outRef: "self.state.intranetEndpoint"
}
masterUserId: {
outRef: "self.state.masterUserId"
}
}
profile: {
baasRepo: string | {
// Example: demoVpc.vpcId
valueRef: string
}
cloudProduct: "AliCloudOSS"
endpoint?: string | {
// Example: demoVpc.vpcId
valueRef: string
}
envType?: "testing" | "product" | {
// Example: demoVpc.vpcId
valueRef: string
}
provider: "alicloud"
region: string | {
// Example: demoVpc.vpcId
valueRef: string
}
serviceAccount?: string | {
// Example: demoVpc.vpcId
valueRef: string
}
}
storageClass?: "IA" | "Archive" | "ColdArchive" | *"Standard"
})
`
bi := build.NewContext().NewInstance("", nil)
mypd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import "kube/test.io/v1"
import "test.io/apps/v1"
output: v1.#Bucket
`)
var r cue.Runtime
@@ -343,66 +417,19 @@ output: v1.#Bucket
assert.NilError(t, err)
base, err := model.NewBase(inst.Value())
assert.NilError(t, err)
assert.Equal(t, base.String(), exceptObj)
exceptObj := `output: close({
kind: "Bucket"
apiVersion: "test.io/v1"
type: "alicloud_oss_bucket"
acl: "public-read-write" | "public-read" | *"private"
dataRedundancyType?: "ZRS" | *"LRS"
dataSourceRef?: close({
dsPath: string
})
importRef?: close({
importKey: string
})
output: close({
{[!~"^(bucketName|extranetEndpoint|intranetEndpoint|masterUserId)$"]: {
outRef: string
} | {
// Example: demoVpc.vpcId
valueRef: string
}}
bucketName: close({
outRef: "self.name"
})
extranetEndpoint: close({
outRef: "self.state.extranetEndpoint"
})
intranetEndpoint: close({
outRef: "self.state.intranetEndpoint"
})
masterUserId: close({
outRef: "self.state.masterUserId"
})
})
profile: close({
baasRepo: string | close({
// Example: demoVpc.vpcId
valueRef: string
})
cloudProduct: "AliCloudOSS"
endpoint?: string | close({
// Example: demoVpc.vpcId
valueRef: string
})
envType?: "testing" | "product" | close({
// Example: demoVpc.vpcId
valueRef: string
})
provider: "alicloud"
region: string | close({
// Example: demoVpc.vpcId
valueRef: string
})
serviceAccount?: string | close({
// Example: demoVpc.vpcId
valueRef: string
})
})
storageClass?: "IA" | "Archive" | "ColdArchive" | *"Standard"
})
`
bi = build.NewContext().NewInstance("", nil)
mypd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", `
import "kube/apps.test.io/v1"
output: v1.#Bucket
`)
inst, err = r.Build(bi)
assert.NilError(t, err)
base, err = model.NewBase(inst.Value())
assert.NilError(t, err)
assert.Equal(t, base.String(), exceptObj)
}
@@ -444,20 +471,20 @@ func TestProcessFile(t *testing.T) {
}
func TestMount(t *testing.T) {
mypd := &PackageDiscover{pkgKinds: make(map[string][]string)}
mypd := &PackageDiscover{pkgKinds: make(map[string][]VersionKind)}
testPkg := newPackage("foo")
mypd.mount(testPkg, []string{"abc"})
mypd.mount(testPkg, []VersionKind{})
assert.Equal(t, len(mypd.velaBuiltinPackages), 1)
mypd.mount(testPkg, []string{"abc"})
mypd.mount(testPkg, []VersionKind{})
assert.Equal(t, len(mypd.velaBuiltinPackages), 1)
assert.Equal(t, mypd.velaBuiltinPackages[0], testPkg.Instance)
}
func TestGetGVK(t *testing.T) {
func TestGetDGVK(t *testing.T) {
srcTmpl := `
{
"x-kubernetes-group-version-kind": {
"group": "test.io",
"group": "apps.test.io",
"kind": "Foo",
"version": "v1"
}
@@ -466,12 +493,34 @@ func TestGetGVK(t *testing.T) {
var r cue.Runtime
inst, err := r.Compile("-", srcTmpl)
assert.NilError(t, err)
gvk, err := getGVK(inst.Value().Lookup("x-kubernetes-group-version-kind"))
gvk, err := getDGVK(inst.Value().Lookup("x-kubernetes-group-version-kind"))
assert.NilError(t, err)
assert.Equal(t, gvk, metav1.GroupVersionKind{
Group: "test.io",
Version: "v1",
Kind: "Foo",
assert.Equal(t, gvk, domainGroupVersionKind{
Domain: "test.io",
Group: "apps",
Version: "v1",
Kind: "Foo",
APIVersion: "apps.test.io/v1",
})
srcTmpl = `
{
"x-kubernetes-group-version-kind": {
"group": "test.io",
"kind": "Foo",
"version": "v1"
}
}
`
inst, err = r.Compile("-", srcTmpl)
assert.NilError(t, err)
gvk, err = getDGVK(inst.Value().Lookup("x-kubernetes-group-version-kind"))
assert.NilError(t, err)
assert.Equal(t, gvk, domainGroupVersionKind{
Group: "test.io",
Version: "v1",
Kind: "Foo",
APIVersion: "test.io/v1",
})
}
@@ -485,7 +534,7 @@ func TestOpenAPIMapping(t *testing.T) {
{
input: []string{"definitions", "io.k8s.api.discovery.v1beta1.Endpoint"},
pos: token.NoPos,
result: "[#Endpoint]",
result: "[io_k8s_api_discovery_v1beta1_Endpoint]",
},
{
input: []string{"definitions", "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaProps"},
@@ -495,7 +544,7 @@ func TestOpenAPIMapping(t *testing.T) {
{
input: []string{"definitions", "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1.JSONSchemaProps"},
pos: token.NoPos,
result: "[#JSONSchemaProps]",
result: "[io_k8s_apiextensions-apiserver_pkg_apis_apiextensions_v1_JSONSchemaProps]",
},
{
input: []string{"definitions"},
@@ -504,8 +553,9 @@ func TestOpenAPIMapping(t *testing.T) {
},
}
emptyMapper := make(map[string]domainGroupVersionKind)
for _, tCase := range testCases {
labels, err := openAPIMapping(tCase.pos, tCase.input)
labels, err := openAPIMapping(emptyMapper)(tCase.pos, tCase.input)
if tCase.errMsg != "" {
assert.Error(t, err, tCase.errMsg)
continue
@@ -515,3 +565,70 @@ func TestOpenAPIMapping(t *testing.T) {
assert.Equal(t, tCase.result, fmt.Sprint(labels))
}
}
func TestGeneratePkgName(t *testing.T) {
testCases := []struct {
dgvk domainGroupVersionKind
sdPkgName string
openPkgName string
}{
{
dgvk: domainGroupVersionKind{
Domain: "k8s.io",
Group: "networking",
Version: "v1",
Kind: "Ingress",
},
sdPkgName: "k8s.io/networking/v1",
openPkgName: "kube/networking.k8s.io",
},
{
dgvk: domainGroupVersionKind{
Group: "example.com",
Version: "v1",
Kind: "Sls",
},
sdPkgName: "example.com/v1",
openPkgName: "kube/example.com/v1",
},
}
for _, tCase := range testCases {
assert.Equal(t, genStandardPkgName(tCase.dgvk), tCase.sdPkgName)
}
}
func TestReverseString(t *testing.T) {
testCases := []struct {
gvr metav1.GroupVersionKind
reverseString string
}{
{
gvr: metav1.GroupVersionKind{
Group: "networking.k8s.io",
Version: "v1",
Kind: "NetworkPolicy",
},
reverseString: "io_k8s_api_networking_v1_NetworkPolicy",
},
{
gvr: metav1.GroupVersionKind{
Group: "example.com",
Version: "v1",
Kind: "Sls",
},
reverseString: "com_example_v1_Sls",
},
{
gvr: metav1.GroupVersionKind{
Version: "v1",
Kind: "Pod",
},
reverseString: "io_k8s_api_core_v1_Pod",
},
}
for _, tCase := range testCases {
assert.Equal(t, convert2DGVK(tCase.gvr).reverseString(), tCase.reverseString)
}
}