forked from mystiq/dex
Merge pull request #2025 from flant/kubernetes-apiextensions-version
feat: create CRDs as apiextensions.k8s.io/v1
This commit is contained in:
commit
033a8d89f2
16 changed files with 387 additions and 171 deletions
1
go.mod
1
go.mod
|
@ -5,6 +5,7 @@ go 1.16
|
||||||
require (
|
require (
|
||||||
entgo.io/ent v0.8.0
|
entgo.io/ent v0.8.0
|
||||||
github.com/AppsFlyer/go-sundheit v0.4.0
|
github.com/AppsFlyer/go-sundheit v0.4.0
|
||||||
|
github.com/Masterminds/semver v1.5.0
|
||||||
github.com/Masterminds/sprig/v3 v3.2.2
|
github.com/Masterminds/sprig/v3 v3.2.2
|
||||||
github.com/beevik/etree v1.1.0
|
github.com/beevik/etree v1.1.0
|
||||||
github.com/coreos/go-oidc/v3 v3.0.0
|
github.com/coreos/go-oidc/v3 v3.0.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -52,6 +52,8 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
|
||||||
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
|
github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: authcodes.dex.coreos.com
|
name: authcodes.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: AuthCodeList
|
listKind: AuthCodeList
|
||||||
plural: authcodes
|
plural: authcodes
|
||||||
singular: authcode
|
singular: authcode
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: authrequests.dex.coreos.com
|
name: authrequests.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: AuthRequestList
|
listKind: AuthRequestList
|
||||||
plural: authrequests
|
plural: authrequests
|
||||||
singular: authrequest
|
singular: authrequest
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: connectors.dex.coreos.com
|
name: connectors.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: ConnectorList
|
listKind: ConnectorList
|
||||||
plural: connectors
|
plural: connectors
|
||||||
singular: connector
|
singular: connector
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: devicerequests.dex.coreos.com
|
name: devicerequests.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: DeviceRequestList
|
listKind: DeviceRequestList
|
||||||
plural: devicerequests
|
plural: devicerequests
|
||||||
singular: devicerequest
|
singular: devicerequest
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: devicetokens.dex.coreos.com
|
name: devicetokens.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: DeviceTokenList
|
listKind: DeviceTokenList
|
||||||
plural: devicetokens
|
plural: devicetokens
|
||||||
singular: devicetoken
|
singular: devicetoken
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: oauth2clients.dex.coreos.com
|
name: oauth2clients.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: OAuth2ClientList
|
listKind: OAuth2ClientList
|
||||||
plural: oauth2clients
|
plural: oauth2clients
|
||||||
singular: oauth2client
|
singular: oauth2client
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: offlinesessionses.dex.coreos.com
|
name: offlinesessionses.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: OfflineSessionsList
|
listKind: OfflineSessionsList
|
||||||
plural: offlinesessionses
|
plural: offlinesessionses
|
||||||
singular: offlinesessions
|
singular: offlinesessions
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: passwords.dex.coreos.com
|
name: passwords.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: PasswordList
|
listKind: PasswordList
|
||||||
plural: passwords
|
plural: passwords
|
||||||
singular: password
|
singular: password
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: refreshtokens.dex.coreos.com
|
name: refreshtokens.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: RefreshTokenList
|
listKind: RefreshTokenList
|
||||||
plural: refreshtokens
|
plural: refreshtokens
|
||||||
singular: refreshtoken
|
singular: refreshtoken
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: signingkeies.dex.coreos.com
|
name: signingkeies.dex.coreos.com
|
||||||
|
@ -9,4 +9,12 @@ spec:
|
||||||
listKind: SigningKeyList
|
listKind: SigningKeyList
|
||||||
plural: signingkeies
|
plural: signingkeies
|
||||||
singular: signingkey
|
singular: signingkey
|
||||||
version: v1
|
scope: Namespaced
|
||||||
|
versions:
|
||||||
|
- name: v1
|
||||||
|
served: true
|
||||||
|
storage: true
|
||||||
|
schema:
|
||||||
|
openAPIV3Schema:
|
||||||
|
type: object
|
||||||
|
x-kubernetes-preserve-unknown-fields: true
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver"
|
||||||
"github.com/ghodss/yaml"
|
"github.com/ghodss/yaml"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
|
|
||||||
|
@ -47,6 +48,10 @@ type client struct {
|
||||||
// API version of the oidc resources. For example "oidc.coreos.com". This is
|
// API version of the oidc resources. For example "oidc.coreos.com". This is
|
||||||
// currently not configurable, but could be in the future.
|
// currently not configurable, but could be in the future.
|
||||||
apiVersion string
|
apiVersion string
|
||||||
|
// API version of the custom resource definitions.
|
||||||
|
// Different Kubernetes version requires to create CRD in certain API. It will be discovered automatically on
|
||||||
|
// storage opening.
|
||||||
|
crdAPIVersion string
|
||||||
|
|
||||||
// This is called once the client's Close method is called to signal goroutines,
|
// This is called once the client's Close method is called to signal goroutines,
|
||||||
// such as the one creating third party resources, to stop.
|
// such as the one creating third party resources, to stop.
|
||||||
|
@ -195,6 +200,37 @@ func (cli *client) postResource(apiVersion, namespace, resource string, v interf
|
||||||
return checkHTTPErr(resp, http.StatusCreated)
|
return checkHTTPErr(resp, http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cli *client) detectKubernetesVersion() error {
|
||||||
|
var version struct{ GitVersion string }
|
||||||
|
|
||||||
|
url := cli.baseURL + "/version"
|
||||||
|
resp, err := cli.client.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer closeResp(resp)
|
||||||
|
if err := checkHTTPErr(resp, http.StatusOK); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.NewDecoder(resp.Body).Decode(&version); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
clusterVersion, err := semver.NewVersion(version.GitVersion)
|
||||||
|
if err != nil {
|
||||||
|
cli.logger.Warnf("cannot detect Kubernetes version (%s): %v", clusterVersion, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if clusterVersion.LessThan(semver.MustParse("v1.16.0")) {
|
||||||
|
cli.crdAPIVersion = legacyCRDAPIVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cli *client) delete(resource, name string) error {
|
func (cli *client) delete(resource, name string) error {
|
||||||
url := cli.urlFor(cli.apiVersion, cli.namespace, resource, name)
|
url := cli.urlFor(cli.apiVersion, cli.namespace, resource, name)
|
||||||
req, err := http.NewRequest("DELETE", url, nil)
|
req, err := http.NewRequest("DELETE", url, nil)
|
||||||
|
@ -351,11 +387,12 @@ func newClient(cluster k8sapi.Cluster, user k8sapi.AuthInfo, namespace string, l
|
||||||
Transport: t,
|
Transport: t,
|
||||||
Timeout: 15 * time.Second,
|
Timeout: 15 * time.Second,
|
||||||
},
|
},
|
||||||
baseURL: cluster.Server,
|
baseURL: cluster.Server,
|
||||||
hash: func() hash.Hash { return fnv.New64() },
|
hash: func() hash.Hash { return fnv.New64() },
|
||||||
namespace: namespace,
|
namespace: namespace,
|
||||||
apiVersion: apiVersion,
|
apiVersion: apiVersion,
|
||||||
logger: logger,
|
crdAPIVersion: crdAPIVersion,
|
||||||
|
logger: logger,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,15 @@ type CustomResourceDefinitionSpec struct {
|
||||||
|
|
||||||
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
|
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
|
||||||
Scope ResourceScope `json:"scope" protobuf:"bytes,4,opt,name=scope,casttype=ResourceScope"`
|
Scope ResourceScope `json:"scope" protobuf:"bytes,4,opt,name=scope,casttype=ResourceScope"`
|
||||||
|
// versions is the list of all API versions of the defined custom resource.
|
||||||
|
// Version names are used to compute the order in which served versions are listed in API discovery.
|
||||||
|
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||||
|
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||||
|
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||||
|
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||||
|
// major version, then minor version. An example sorted list of versions:
|
||||||
|
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||||
|
Versions []CustomResourceDefinitionVersion `json:"versions" protobuf:"bytes,7,rep,name=versions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
|
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
|
||||||
|
@ -139,3 +148,29 @@ type CustomResourceDefinitionList struct {
|
||||||
// Items individual CustomResourceDefinitions
|
// Items individual CustomResourceDefinitions
|
||||||
Items []CustomResourceDefinition `json:"items" protobuf:"bytes,2,rep,name=items"`
|
Items []CustomResourceDefinition `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CustomResourceDefinitionVersion struct {
|
||||||
|
// name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||||
|
// The custom resources are served under this version at `/apis/<group>/<version>/...` if `served` is true.
|
||||||
|
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||||
|
// served is a flag enabling/disabling this version from being served via REST APIs
|
||||||
|
Served bool `json:"served" protobuf:"varint,2,opt,name=served"`
|
||||||
|
// storage indicates this version should be used when persisting custom resources to storage.
|
||||||
|
// There must be exactly one version with storage=true.
|
||||||
|
Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"`
|
||||||
|
// schema describes the schema used for validation, pruning, and defaulting of this version of the custom resource.
|
||||||
|
// +optional
|
||||||
|
Schema *CustomResourceValidation `json:"schema,omitempty" protobuf:"bytes,4,opt,name=schema"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||||
|
type CustomResourceValidation struct {
|
||||||
|
// OpenAPIV3Schema is the OpenAPI v3 schema to be validated against.
|
||||||
|
OpenAPIV3Schema *JSONSchemaProps `json:"openAPIV3Schema,omitempty" protobuf:"bytes,1,opt,name=openAPIV3Schema"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||||
|
type JSONSchemaProps struct {
|
||||||
|
Type string `json:"type,omitempty" protobuf:"bytes,5,opt,name=type"`
|
||||||
|
XPreserveUnknownFields *bool `json:"x-kubernetes-preserve-unknown-fields,omitempty" protobuf:"bytes,38,opt,name=xKubernetesPreserveUnknownFields"`
|
||||||
|
}
|
||||||
|
|
|
@ -88,6 +88,10 @@ func (c *Config) open(logger log.Logger, waitForResources bool) (*client, error)
|
||||||
return nil, fmt.Errorf("create client: %v", err)
|
return nil, fmt.Errorf("create client: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = cli.detectKubernetesVersion(); err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot get kubernetes version: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
logger.Info("creating custom Kubernetes resources")
|
logger.Info("creating custom Kubernetes resources")
|
||||||
|
@ -100,7 +104,6 @@ func (c *Config) open(logger log.Logger, waitForResources bool) (*client, error)
|
||||||
// Try to synchronously create the custom resources once. This doesn't mean
|
// Try to synchronously create the custom resources once. This doesn't mean
|
||||||
// they'll immediately be available, but ensures that the client will actually try
|
// they'll immediately be available, but ensures that the client will actually try
|
||||||
// once.
|
// once.
|
||||||
logger.Errorf("failed creating custom resources: %v", err)
|
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
if cli.registerCustomResources() {
|
if cli.registerCustomResources() {
|
||||||
|
@ -136,21 +139,25 @@ func (c *Config) open(logger log.Logger, waitForResources bool) (*client, error)
|
||||||
// Creating a custom resource does not mean that they'll be immediately available.
|
// Creating a custom resource does not mean that they'll be immediately available.
|
||||||
func (cli *client) registerCustomResources() (ok bool) {
|
func (cli *client) registerCustomResources() (ok bool) {
|
||||||
ok = true
|
ok = true
|
||||||
length := len(customResourceDefinitions)
|
|
||||||
|
definitions := customResourceDefinitions(cli.crdAPIVersion)
|
||||||
|
length := len(definitions)
|
||||||
|
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
var err error
|
var err error
|
||||||
var resourceName string
|
var resourceName string
|
||||||
|
|
||||||
r := customResourceDefinitions[i]
|
r := definitions[i]
|
||||||
var i interface{}
|
var i interface{}
|
||||||
cli.logger.Infof("checking if custom resource %s has been created already...", r.ObjectMeta.Name)
|
cli.logger.Infof("checking if custom resource %s has already been created...", r.ObjectMeta.Name)
|
||||||
if err := cli.list(r.Spec.Names.Plural, &i); err == nil {
|
if err := cli.list(r.Spec.Names.Plural, &i); err == nil {
|
||||||
cli.logger.Infof("The custom resource %s already available, skipping create", r.ObjectMeta.Name)
|
cli.logger.Infof("The custom resource %s already available, skipping create", r.ObjectMeta.Name)
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
cli.logger.Infof("failed to list custom resource %s, attempting to create: %v", r.ObjectMeta.Name, err)
|
cli.logger.Infof("failed to list custom resource %s, attempting to create: %v", r.ObjectMeta.Name, err)
|
||||||
}
|
}
|
||||||
err = cli.postResource("apiextensions.k8s.io/v1beta1", "", "customresourcedefinitions", r)
|
|
||||||
|
err = cli.postResource(cli.crdAPIVersion, "", "customresourcedefinitions", r)
|
||||||
resourceName = r.ObjectMeta.Name
|
resourceName = r.ObjectMeta.Name
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -177,7 +184,7 @@ func (cli *client) waitForCRDs(ctx context.Context) error {
|
||||||
ctx, cancel := context.WithTimeout(ctx, time.Second*30)
|
ctx, cancel := context.WithTimeout(ctx, time.Second*30)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
for _, crd := range customResourceDefinitions {
|
for _, crd := range customResourceDefinitions(cli.crdAPIVersion) {
|
||||||
for {
|
for {
|
||||||
err := cli.isCRDReady(crd.Name)
|
err := cli.isCRDReady(crd.Name)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -199,7 +206,7 @@ func (cli *client) waitForCRDs(ctx context.Context) error {
|
||||||
// isCRDReady determines if a CRD is ready by inspecting its conditions.
|
// isCRDReady determines if a CRD is ready by inspecting its conditions.
|
||||||
func (cli *client) isCRDReady(name string) error {
|
func (cli *client) isCRDReady(name string) error {
|
||||||
var r k8sapi.CustomResourceDefinition
|
var r k8sapi.CustomResourceDefinition
|
||||||
err := cli.getResource("apiextensions.k8s.io/v1beta1", "", "customresourcedefinitions", name, &r)
|
err := cli.getResource(cli.crdAPIVersion, "", "customresourcedefinitions", name, &r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get crd %s: %v", name, err)
|
return fmt.Errorf("get crd %s: %v", name, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,169 +10,223 @@ import (
|
||||||
"github.com/dexidp/dex/storage/kubernetes/k8sapi"
|
"github.com/dexidp/dex/storage/kubernetes/k8sapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
var crdMeta = k8sapi.TypeMeta{
|
const (
|
||||||
APIVersion: "apiextensions.k8s.io/v1beta1",
|
apiGroup = "dex.coreos.com"
|
||||||
Kind: "CustomResourceDefinition",
|
|
||||||
}
|
|
||||||
|
|
||||||
const apiGroup = "dex.coreos.com"
|
legacyCRDAPIVersion = "apiextensions.k8s.io/v1beta1"
|
||||||
|
crdAPIVersion = "apiextensions.k8s.io/v1"
|
||||||
|
)
|
||||||
|
|
||||||
// The set of custom resource definitions required by the storage. These are managed by
|
// The set of custom resource definitions required by the storage. These are managed by
|
||||||
// the storage so it can migrate itself by creating new resources.
|
// the storage so it can migrate itself by creating new resources.
|
||||||
var customResourceDefinitions = []k8sapi.CustomResourceDefinition{
|
func customResourceDefinitions(apiVersion string) []k8sapi.CustomResourceDefinition {
|
||||||
{
|
crdMeta := k8sapi.TypeMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
APIVersion: apiVersion,
|
||||||
Name: "authcodes.dex.coreos.com",
|
Kind: "CustomResourceDefinition",
|
||||||
},
|
}
|
||||||
TypeMeta: crdMeta,
|
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
var version string
|
||||||
Group: apiGroup,
|
var scope k8sapi.ResourceScope
|
||||||
Version: "v1",
|
var versions []k8sapi.CustomResourceDefinitionVersion
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
|
||||||
Plural: "authcodes",
|
switch apiVersion {
|
||||||
Singular: "authcode",
|
case crdAPIVersion:
|
||||||
Kind: "AuthCode",
|
preserveUnknownFields := true
|
||||||
|
versions = []k8sapi.CustomResourceDefinitionVersion{
|
||||||
|
{
|
||||||
|
Name: "v1",
|
||||||
|
Served: true,
|
||||||
|
Storage: true,
|
||||||
|
Schema: &k8sapi.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &k8sapi.JSONSchemaProps{
|
||||||
|
Type: "object",
|
||||||
|
XPreserveUnknownFields: &preserveUnknownFields,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scope = k8sapi.NamespaceScoped
|
||||||
|
case legacyCRDAPIVersion:
|
||||||
|
version = "v1"
|
||||||
|
default:
|
||||||
|
panic("unknown apiVersion " + apiVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
return []k8sapi.CustomResourceDefinition{
|
||||||
|
{
|
||||||
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
|
Name: "authcodes.dex.coreos.com",
|
||||||
|
},
|
||||||
|
TypeMeta: crdMeta,
|
||||||
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
|
Group: apiGroup,
|
||||||
|
Version: version,
|
||||||
|
Versions: versions,
|
||||||
|
Scope: scope,
|
||||||
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
|
Plural: "authcodes",
|
||||||
|
Singular: "authcode",
|
||||||
|
Kind: "AuthCode",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "authrequests.dex.coreos.com",
|
||||||
Name: "authrequests.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "authrequests",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "authrequest",
|
Plural: "authrequests",
|
||||||
Kind: "AuthRequest",
|
Singular: "authrequest",
|
||||||
|
Kind: "AuthRequest",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "oauth2clients.dex.coreos.com",
|
||||||
Name: "oauth2clients.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "oauth2clients",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "oauth2client",
|
Plural: "oauth2clients",
|
||||||
Kind: "OAuth2Client",
|
Singular: "oauth2client",
|
||||||
|
Kind: "OAuth2Client",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "signingkeies.dex.coreos.com",
|
||||||
Name: "signingkeies.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
// `signingkeies` is an artifact from the old TPR pluralization.
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
// Users don't directly interact with this value, hence leaving it
|
// `signingkeies` is an artifact from the old TPR pluralization.
|
||||||
// as is.
|
// Users don't directly interact with this value, hence leaving it
|
||||||
Plural: "signingkeies",
|
// as is.
|
||||||
Singular: "signingkey",
|
Plural: "signingkeies",
|
||||||
Kind: "SigningKey",
|
Singular: "signingkey",
|
||||||
|
Kind: "SigningKey",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "refreshtokens.dex.coreos.com",
|
||||||
Name: "refreshtokens.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "refreshtokens",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "refreshtoken",
|
Plural: "refreshtokens",
|
||||||
Kind: "RefreshToken",
|
Singular: "refreshtoken",
|
||||||
|
Kind: "RefreshToken",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "passwords.dex.coreos.com",
|
||||||
Name: "passwords.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "passwords",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "password",
|
Plural: "passwords",
|
||||||
Kind: "Password",
|
Singular: "password",
|
||||||
|
Kind: "Password",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "offlinesessionses.dex.coreos.com",
|
||||||
Name: "offlinesessionses.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "offlinesessionses",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "offlinesessions",
|
Plural: "offlinesessionses",
|
||||||
Kind: "OfflineSessions",
|
Singular: "offlinesessions",
|
||||||
|
Kind: "OfflineSessions",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "connectors.dex.coreos.com",
|
||||||
Name: "connectors.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "connectors",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "connector",
|
Plural: "connectors",
|
||||||
Kind: "Connector",
|
Singular: "connector",
|
||||||
|
Kind: "Connector",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "devicerequests.dex.coreos.com",
|
||||||
Name: "devicerequests.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "devicerequests",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "devicerequest",
|
Plural: "devicerequests",
|
||||||
Kind: "DeviceRequest",
|
Singular: "devicerequest",
|
||||||
|
Kind: "DeviceRequest",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
{
|
||||||
{
|
ObjectMeta: k8sapi.ObjectMeta{
|
||||||
ObjectMeta: k8sapi.ObjectMeta{
|
Name: "devicetokens.dex.coreos.com",
|
||||||
Name: "devicetokens.dex.coreos.com",
|
},
|
||||||
},
|
TypeMeta: crdMeta,
|
||||||
TypeMeta: crdMeta,
|
Spec: k8sapi.CustomResourceDefinitionSpec{
|
||||||
Spec: k8sapi.CustomResourceDefinitionSpec{
|
Group: apiGroup,
|
||||||
Group: apiGroup,
|
Version: version,
|
||||||
Version: "v1",
|
Versions: versions,
|
||||||
Names: k8sapi.CustomResourceDefinitionNames{
|
Scope: scope,
|
||||||
Plural: "devicetokens",
|
Names: k8sapi.CustomResourceDefinitionNames{
|
||||||
Singular: "devicetoken",
|
Plural: "devicetokens",
|
||||||
Kind: "DeviceToken",
|
Singular: "devicetoken",
|
||||||
|
Kind: "DeviceToken",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// There will only ever be a single keys resource. Maintain this by setting a
|
// There will only ever be a single keys resource. Maintain this by setting a
|
||||||
|
|
Loading…
Reference in a new issue