Merge pull request #1802 from XiShanYongYe-Chang/karmada-search

Add karmada-search fabric
This commit is contained in:
karmada-bot 2022-05-17 10:48:46 +08:00 committed by GitHub
commit 5577f05587
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 1508 additions and 344 deletions

View File

@ -21,6 +21,7 @@ jobs:
- karmada-scheduler-estimator
- karmada-interpreter-webhook-example
- karmada-aggregated-apiserver
- karmada-search
runs-on: ubuntu-18.04
steps:
- name: checkout code

View File

@ -17,6 +17,7 @@ jobs:
- karmada-scheduler-estimator
- karmada-interpreter-webhook-example
- karmada-aggregated-apiserver
- karmada-search
runs-on: ubuntu-18.04
steps:
- name: checkout code

1
.gitignore vendored
View File

@ -30,6 +30,7 @@ _output/
/karmada-scheduler-estimator
/karmada-webhook
/kubectl-karmada
/karmada-search
# OSX trash
.DS_Store

View File

@ -28,7 +28,8 @@ TARGETS := karmada-aggregated-apiserver \
karmada-webhook \
karmada-agent \
karmada-scheduler-estimator \
karmada-interpreter-webhook-example
karmada-interpreter-webhook-example \
karmada-search
CTL_TARGETS := karmadactl kubectl-karmada
@ -122,3 +123,4 @@ endif
docker push ${REGISTRY}/karmada-scheduler-estimator:${VERSION}
docker push ${REGISTRY}/karmada-interpreter-webhook-example:${VERSION}
docker push ${REGISTRY}/karmada-aggregated-apiserver:${VERSION}
docker push ${REGISTRY}/karmada-search:${VERSION}

View File

@ -0,0 +1,25 @@
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1alpha1.search.karmada.io
labels:
app: karmada-search
apiserver: "true"
spec:
insecureSkipTLSVerify: true
group: search.karmada.io
groupPriorityMinimum: 2000
service:
name: karmada-search
namespace: karmada-system
version: v1alpha1
versionPriority: 10
---
apiVersion: v1
kind: Service
metadata:
name: karmada-search
namespace: karmada-system
spec:
type: ExternalName
externalName: karmada-search.karmada-system.svc.cluster.local

View File

@ -0,0 +1,74 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: karmada-search
namespace: karmada-system
labels:
app: karmada-search
apiserver: "true"
spec:
selector:
matchLabels:
app: karmada-search
apiserver: "true"
replicas: 2
template:
metadata:
labels:
app: karmada-search
apiserver: "true"
spec:
automountServiceAccountToken: false
containers:
- name: karmada-search
image: swr.ap-southeast-1.myhuaweicloud.com/karmada/karmada-search:latest
imagePullPolicy: IfNotPresent
volumeMounts:
- name: k8s-certs
mountPath: /etc/kubernetes/pki
readOnly: true
- name: kubeconfig
subPath: kubeconfig
mountPath: /etc/kubeconfig
command:
- /bin/karmada-search
- --kubeconfig=/etc/kubeconfig
- --authentication-kubeconfig=/etc/kubeconfig
- --authorization-kubeconfig=/etc/kubeconfig
- --etcd-servers=https://etcd-client.karmada-system.svc.cluster.local:2379
- --etcd-cafile=/etc/kubernetes/pki/server-ca.crt
- --etcd-certfile=/etc/kubernetes/pki/karmada.crt
- --etcd-keyfile=/etc/kubernetes/pki/karmada.key
- --tls-cert-file=/etc/kubernetes/pki/karmada.crt
- --tls-private-key-file=/etc/kubernetes/pki/karmada.key
- --audit-log-path=-
- --feature-gates=APIPriorityAndFairness=false
- --audit-log-maxage=0
- --audit-log-maxbackup=0
resources:
requests:
cpu: 100m
volumes:
- name: k8s-certs
secret:
secretName: karmada-cert-secret
- name: kubeconfig
secret:
secretName: kubeconfig
---
apiVersion: v1
kind: Service
metadata:
name: karmada-search
namespace: karmada-system
labels:
app: karmada-search
apiserver: "true"
spec:
ports:
- port: 443
protocol: TCP
targetPort: 443
selector:
app: karmada-search

View File

@ -1,253 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.8.0
creationTimestamp: null
name: resourceregistries.search.karmada.io
spec:
group: search.karmada.io
names:
kind: ResourceRegistry
listKind: ResourceRegistryList
plural: resourceregistries
singular: resourceregistry
scope: Cluster
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: ResourceRegistry defines a list of member cluster to be cached.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: Spec represents the desired behavior of ResourceRegistry.
properties:
clusterSelectors:
description: ClusterSelectors represents the filter to select clusters.
items:
description: ClusterSelector represents the filter to select clusters.
properties:
clusterNames:
description: ClusterNames is the list of clusters to be selected.
items:
type: string
type: array
exclude:
description: ExcludedClusters is the list of clusters to be
ignored.
items:
type: string
type: array
fieldSelector:
description: FieldSelector is a filter to select member clusters
by fields. If non-nil and non-empty, only the clusters match
this filter will be selected.
properties:
matchExpressions:
description: A list of field selector requirements.
items:
description: A node selector requirement is a selector
that contains values, a key, and an operator that relates
the key and values.
properties:
key:
description: The label key that the selector applies
to.
type: string
operator:
description: Represents a key's relationship to a
set of values. Valid operators are In, NotIn, Exists,
DoesNotExist. Gt, and Lt.
type: string
values:
description: An array of string values. If the operator
is In or NotIn, the values array must be non-empty.
If the operator is Exists or DoesNotExist, the values
array must be empty. If the operator is Gt or Lt,
the values array must have a single element, which
will be interpreted as an integer. This array is
replaced during a strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
type: object
labelSelector:
description: LabelSelector is a filter to select member clusters
by labels. If non-nil and non-empty, only the clusters match
this filter will be selected.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: A label selector requirement is a selector
that contains values, a key, and an operator that relates
the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: operator represents a key's relationship
to a set of values. Valid operators are In, NotIn,
Exists and DoesNotExist.
type: string
values:
description: values is an array of string values.
If the operator is In or NotIn, the values array
must be non-empty. If the operator is Exists or
DoesNotExist, the values array must be empty. This
array is replaced during a strategic merge patch.
items:
type: string
type: array
required:
- key
- operator
type: object
type: array
matchLabels:
additionalProperties:
type: string
description: matchLabels is a map of {key,value} pairs.
A single {key,value} in the matchLabels map is equivalent
to an element of matchExpressions, whose key field is
"key", the operator is "In", and the values array contains
only "value". The requirements are ANDed.
type: object
type: object
type: object
type: array
resourceSelectors:
description: ResourceSelectors used to select resources.
items:
description: ResourceSelector the resources will be selected.
properties:
apiVersion:
description: APIVersion represents the API version of the target
resources.
type: string
kind:
description: Kind represents the Kind of the target resources.
type: string
namespace:
description: Namespace of the target resource. Default is empty,
which means all namespaces.
type: string
required:
- apiVersion
- kind
type: object
type: array
statusUpdatePeriodSeconds:
description: StatusUpdatePeriodSeconds is the period to update the
status of the resource. default is 10s.
format: int32
type: integer
required:
- clusterSelectors
- resourceSelectors
type: object
status:
description: Status represents the status of ResoruceRegistry.
properties:
conditions:
description: Conditions contain the different condition statuses.
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
type FooStatus struct{ // Represents the observations of a foo's
current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -80,7 +80,7 @@ data:
{{- include "karmada.webhook.configuration" . | nindent 8 }}
{{- print "system-namespace.yaml: " | nindent 6 }} |-
{{- include "karmada.systemNamespace" . | nindent 8 }}
{{- print "apiservice.yaml: " | nindent 6 }} |-
{{- print "karmada-aggregated-apiserver-apiservice.yaml: " | nindent 6 }} |-
{{- include "karmada.apiservice" . | nindent 8 }}
{{- print "cluster-proxy-admin-rbac.yaml: " | nindent 6 }} |-
{{- include "karmada.proxyRbac" . | nindent 8 }}

View File

@ -0,0 +1,54 @@
package app
import (
"context"
"os"
"github.com/spf13/cobra"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/component-base/term"
"github.com/karmada-io/karmada/cmd/karmada-search/app/options"
"github.com/karmada-io/karmada/pkg/sharedcli"
"github.com/karmada-io/karmada/pkg/sharedcli/klogflag"
"github.com/karmada-io/karmada/pkg/version/sharedcommand"
)
// NewKarmadaSearchCommand creates a *cobra.Command object with default parameters
func NewKarmadaSearchCommand(ctx context.Context) *cobra.Command {
opts := options.NewOptions()
cmd := &cobra.Command{
Use: "karmada-search",
Long: `Launch the karmada-search`,
RunE: func(cmd *cobra.Command, args []string) error {
if err := opts.Complete(); err != nil {
return err
}
if err := opts.Validate(); err != nil {
return err
}
if err := opts.Run(ctx); err != nil {
return err
}
return nil
},
}
fss := cliflag.NamedFlagSets{}
genericFlagSet := fss.FlagSet("generic")
opts.AddFlags(genericFlagSet)
// Set klog flags
logsFlagSet := fss.FlagSet("logs")
klogflag.Add(logsFlagSet)
cmd.AddCommand(sharedcommand.NewCmdVersion(os.Stdout, "karmada-search"))
cmd.Flags().AddFlagSet(genericFlagSet)
cmd.Flags().AddFlagSet(logsFlagSet)
cols, _, _ := term.TerminalSize(cmd.OutOrStdout())
sharedcli.SetUsageAndHelpFunc(cmd, fss, cols)
return cmd
}

View File

@ -0,0 +1,115 @@
package options
import (
"context"
"fmt"
"net"
"github.com/spf13/pflag"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apiserver/pkg/endpoints/openapi"
"k8s.io/apiserver/pkg/features"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes"
netutils "k8s.io/utils/net"
searchv1alpha1 "github.com/karmada-io/karmada/pkg/apis/search/v1alpha1"
generatedopenapi "github.com/karmada-io/karmada/pkg/generated/openapi"
"github.com/karmada-io/karmada/pkg/search"
)
const defaultEtcdPathPrefix = "/registry"
// Options contains everything necessary to create and run karmada-search.
type Options struct {
RecommendedOptions *genericoptions.RecommendedOptions
// KubeAPIQPS is the QPS to use while talking with karmada-search.
KubeAPIQPS float32
// KubeAPIBurst is the burst to allow while talking with karmada-search.
KubeAPIBurst int
}
// NewOptions returns a new Options.
func NewOptions() *Options {
o := &Options{
RecommendedOptions: genericoptions.NewRecommendedOptions(
defaultEtcdPathPrefix,
search.Codecs.LegacyCodec(searchv1alpha1.SchemeGroupVersion)),
}
o.RecommendedOptions.Etcd.StorageConfig.EncodeVersioner = runtime.NewMultiGroupVersioner(searchv1alpha1.SchemeGroupVersion,
schema.GroupKind{Group: searchv1alpha1.GroupName})
o.RecommendedOptions.Etcd.StorageConfig.Paging = utilfeature.DefaultFeatureGate.Enabled(features.APIListChunking)
return o
}
// AddFlags adds flags to the specified FlagSet.
func (o *Options) AddFlags(flags *pflag.FlagSet) {
o.RecommendedOptions.AddFlags(flags)
flags.Lookup("kubeconfig").Usage = "Path to karmada control plane kubeconfig file."
flags.Float32Var(&o.KubeAPIQPS, "kube-api-qps", 40.0, "QPS to use while talking with karmada-apiserver. Doesn't cover events and node heartbeat apis which rate limiting is controlled by a different set of flags.")
flags.IntVar(&o.KubeAPIBurst, "kube-api-burst", 60, "Burst to use while talking with karmada-apiserver. Doesn't cover events and node heartbeat apis which rate limiting is controlled by a different set of flags.")
utilfeature.DefaultMutableFeatureGate.AddFlag(flags)
}
// Complete fills in fields required to have valid data.
func (o *Options) Complete() error {
return nil
}
// Validate validates Options.
func (o *Options) Validate() error {
var errs []error
errs = append(errs, o.RecommendedOptions.Validate()...)
return utilerrors.NewAggregate(errs)
}
// Run runs the aggregated-apiserver with options. This should never exit.
func (o *Options) Run(ctx context.Context) error {
config, err := o.Config()
if err != nil {
return err
}
restConfig := config.GenericConfig.ClientConfig
restConfig.QPS, restConfig.Burst = o.KubeAPIQPS, o.KubeAPIBurst
kubeClientSet := kubernetes.NewForConfigOrDie(restConfig)
server, err := config.Complete().New(kubeClientSet)
if err != nil {
return err
}
server.GenericAPIServer.AddPostStartHookOrDie("start-karmada-search-informers", func(context genericapiserver.PostStartHookContext) error {
config.GenericConfig.SharedInformerFactory.Start(context.StopCh)
return nil
})
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
}
// Config returns config for the api server given Options
func (o *Options) Config() (*search.Config, error) {
// TODO have a "real" external address
if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{netutils.ParseIPSloppy("127.0.0.1")}); err != nil {
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
}
serverConfig := genericapiserver.NewRecommendedConfig(search.Codecs)
serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(generatedopenapi.GetOpenAPIDefinitions, openapi.NewDefinitionNamer(search.Scheme))
serverConfig.OpenAPIConfig.Info.Title = "karmada-search"
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
return nil, err
}
config := &search.Config{
GenericConfig: serverConfig,
ExtraConfig: search.ExtraConfig{},
}
return config, nil
}

View File

@ -0,0 +1,28 @@
package main
import (
"os"
apiserver "k8s.io/apiserver/pkg/server"
"k8s.io/component-base/logs"
"github.com/karmada-io/karmada/cmd/karmada-search/app"
)
func main() {
if err := runKarmadaSearchCmd(); err != nil {
os.Exit(1)
}
}
func runKarmadaSearchCmd() error {
logs.InitLogs()
defer logs.FlushLogs()
ctx := apiserver.SetupSignalContext()
if err := app.NewKarmadaSearchCommand(ctx).Execute(); err != nil {
return err
}
return nil
}

View File

@ -208,6 +208,9 @@ kubectl apply -f "${REPO_ROOT}/artifacts/deploy/kube-controller-manager.yaml"
# deploy aggregated-apiserver on host cluster
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/karmada-aggregated-apiserver.yaml"
util::wait_pod_ready "${KARMADA_AGGREGATION_APISERVER_LABEL}" "${KARMADA_SYSTEM_NAMESPACE}"
# deploy karmada-search on host cluster
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/karmada-search.yaml"
util::wait_pod_ready "${KARMADA_SEARCH_LABEL}" "${KARMADA_SYSTEM_NAMESPACE}"
# install CRD APIs on karmada apiserver.
if ! kubectl config use-context karmada-apiserver > /dev/null 2>&1;
@ -228,10 +231,15 @@ rm -rf "${TEMP_PATH_CRDS}"
util::deploy_webhook_configuration "${ROOT_CA_FILE}" "${REPO_ROOT}/artifacts/deploy/webhook-configuration.yaml"
# deploy APIService on karmada apiserver for karmada-aggregated-apiserver
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/apiservice.yaml"
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/karmada-aggregated-apiserver-apiservice.yaml"
# make sure apiservice for v1alpha1.cluster.karmada.io is Available
util::wait_apiservice_ready "${KARMADA_AGGREGATION_APISERVER_LABEL}"
# deploy APIService on karmada apiserver for karmada-search
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/karmada-search-apiservice.yaml"
# make sure apiservice for v1alpha1.search.karmada.io is Available
util::wait_apiservice_ready "${KARMADA_SEARCH_LABEL}"
# deploy cluster proxy rbac for admin
kubectl apply -f "${REPO_ROOT}/artifacts/deploy/cluster-proxy-admin-rbac.yaml"

View File

@ -124,6 +124,7 @@ kind load docker-image "${REGISTRY}/karmada-descheduler:${VERSION}" --name="${HO
kind load docker-image "${REGISTRY}/karmada-webhook:${VERSION}" --name="${HOST_CLUSTER_NAME}"
kind load docker-image "${REGISTRY}/karmada-scheduler-estimator:${VERSION}" --name="${HOST_CLUSTER_NAME}"
kind load docker-image "${REGISTRY}/karmada-aggregated-apiserver:${VERSION}" --name="${HOST_CLUSTER_NAME}"
kind load docker-image "${REGISTRY}/karmada-search:${VERSION}" --name="${HOST_CLUSTER_NAME}"
#step5. install karmada control plane components
"${REPO_ROOT}"/hack/deploy-karmada.sh "${MAIN_KUBECONFIG}" "${HOST_CLUSTER_NAME}"

View File

@ -76,6 +76,11 @@ deepcopy-gen \
--input-dirs=github.com/karmada-io/karmada/pkg/apis/search/v1alpha1 \
--output-package=github.com/karmada-io/karmada/pkg/apis/search/v1alpha1 \
--output-file-base=zz_generated.deepcopy
deepcopy-gen \
--go-header-file hack/boilerplate/boilerplate.go.txt \
--input-dirs=github.com/karmada-io/karmada/pkg/apis/search \
--output-package=github.com/karmada-io/karmada/pkg/apis/search \
--output-file-base=zz_generated.deepcopy
echo "Generating with register-gen"
register-gen \
@ -125,6 +130,11 @@ conversion-gen \
--input-dirs=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1 \
--output-package=github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1 \
--output-file-base=zz_generated.conversion
conversion-gen \
--go-header-file hack/boilerplate/boilerplate.go.txt \
--input-dirs=github.com/karmada-io/karmada/pkg/apis/search/v1alpha1 \
--output-package=github.com/karmada-io/karmada/pkg/apis/search/v1alpha1 \
--output-file-base=zz_generated.conversion
echo "Generating with client-gen"
client-gen \

View File

@ -18,4 +18,3 @@ controller-gen crd paths=./pkg/apis/policy/... output:crd:dir=./charts/_crds/bas
controller-gen crd paths=./pkg/apis/work/... output:crd:dir=./charts/_crds/bases
controller-gen crd paths=./pkg/apis/networking/... output:crd:dir=./charts/_crds/bases
controller-gen crd paths=./examples/customresourceinterpreter/apis/... output:crd:dir=./examples/customresourceinterpreter/apis/
controller-gen crd paths=./pkg/apis/search/... output:crd:dir=./charts/_crds/bases

View File

@ -16,6 +16,7 @@ KARMADA_SCHEDULER_LABEL="karmada-scheduler"
KARMADA_WEBHOOK_LABEL="karmada-webhook"
AGENT_POD_LABEL="karmada-agent"
INTERPRETER_WEBHOOK_EXAMPLE_LABEL="karmada-interpreter-webhook-example"
KARMADA_SEARCH_LABEL="karmada-search"
KARMADA_GO_PACKAGE="github.com/karmada-io/karmada"
@ -32,6 +33,7 @@ KARMADA_TARGET_SOURCE=(
karmada-agent=cmd/agent
karmada-scheduler-estimator=cmd/scheduler-estimator
karmada-interpreter-webhook-example=examples/customresourceinterpreter/webhook
karmada-search=cmd/karmada-search
)
#https://textkool.com/en/ascii-art-generator?hl=default&vl=default&font=DOS%20Rebel&text=KARMADA

View File

@ -0,0 +1,107 @@
package search
import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ResourceRegistry defines a list of member cluster to be cached.
type ResourceRegistry struct {
metav1.TypeMeta
metav1.ObjectMeta
// Spec represents the desired behavior of ResourceRegistry.
Spec ResourceRegistrySpec
// Status represents the status of ResoruceRegistry.
// +optional
Status ResourceRegistryStatus
}
// ResourceRegistrySpec defines the desired state of ResourceRegistry.
type ResourceRegistrySpec struct {
// ClusterSelectors represents the filter to select clusters.
// +required
ClusterSelectors []ClusterSelector
// ResourceSelectors used to select resources.
// +required
ResourceSelectors []ResourceSelector
// StatusUpdatePeriodSeconds is the period to update the status of the resource.
// default is 10s.
// +optional
StatusUpdatePeriodSeconds uint32
}
// ClusterSelector represents the filter to select clusters.
type ClusterSelector struct {
// LabelSelector is a filter to select member clusters by labels.
// If non-nil and non-empty, only the clusters match this filter will be selected.
// +optional
LabelSelector *metav1.LabelSelector
// FieldSelector is a filter to select member clusters by fields.
// If non-nil and non-empty, only the clusters match this filter will be selected.
// +optional
FieldSelector *FieldSelector
// ClusterNames is the list of clusters to be selected.
// +optional
ClusterNames []string
// ExcludedClusters is the list of clusters to be ignored.
// +optional
ExcludeClusters []string
}
// FieldSelector is a field filter.
type FieldSelector struct {
// A list of field selector requirements.
MatchExpressions []corev1.NodeSelectorRequirement
}
// ResourceSelector the resources will be selected.
type ResourceSelector struct {
// APIVersion represents the API version of the target resources.
// +required
APIVersion string
// Kind represents the Kind of the target resources.
// +required
Kind string
// Namespace of the target resource.
// Default is empty, which means all namespaces.
// +optional
Namespace string
}
// ResourceRegistryStatus defines the observed state of ResourceRegistry
type ResourceRegistryStatus struct {
// Conditions contain the different condition statuses.
// +optional
Conditions []metav1.Condition
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// ResourceRegistryList if a collection of ResourceRegistry.
type ResourceRegistryList struct {
metav1.TypeMeta
metav1.ListMeta
// Items holds a list of ResourceRegistry.
Items []ResourceRegistry
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Search define a flag for resource search that do not have actual resources.
type Search struct {
metav1.TypeMeta
}

4
pkg/apis/search/doc.go Normal file
View File

@ -0,0 +1,4 @@
// Package search is the internal version of the API.
// +k8s:deepcopy-gen=package
// +groupName=search.karmada.io
package search

View File

@ -0,0 +1,16 @@
package install
import (
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"github.com/karmada-io/karmada/pkg/apis/search"
searchv1alpha1 "github.com/karmada-io/karmada/pkg/apis/search/v1alpha1"
)
// Install registers the API group and adds types to a scheme.
func Install(scheme *runtime.Scheme) {
utilruntime.Must(search.AddToScheme(scheme))
utilruntime.Must(searchv1alpha1.AddToScheme(scheme))
utilruntime.Must(scheme.SetVersionPriority(searchv1alpha1.SchemeGroupVersion))
}

View File

@ -0,0 +1,39 @@
package search
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// GroupName specifies the group name used to register the objects.
const GroupName = "search.karmada.io"
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}
// Kind takes an unqualified kind and returns a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}
var (
// SchemeBuilder is the scheme builder with scheme init functions to run for this API package
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme is a common registration function for mapping packaged scoped group & version keys to a scheme
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ResourceRegistry{},
&ResourceRegistryList{},
&Search{},
)
return nil
}

View File

@ -17,9 +17,8 @@ const (
)
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope="Cluster"
// ResourceRegistry defines a list of member cluster to be cached.
type ResourceRegistry struct {
@ -111,3 +110,10 @@ type ResourceRegistryList struct {
// Items holds a list of ResourceRegistry.
Items []ResourceRegistry `json:"items"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// Search define a flag for resource search that do not have actual resources.
type Search struct {
metav1.TypeMeta `json:",inline"`
}

View File

@ -1,5 +1,6 @@
// Package v1alpha1 is the v1alpha1 version of the API.
// +k8s:deepcopy-gen=package,register
// +k8s:openapi-gen=true
// +k8s:conversion-gen=github.com/karmada-io/karmada/pkg/apis/search
// +groupName=search.karmada.io
package v1alpha1

View File

@ -0,0 +1,292 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// Code generated by conversion-gen. DO NOT EDIT.
package v1alpha1
import (
unsafe "unsafe"
search "github.com/karmada-io/karmada/pkg/apis/search"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
conversion "k8s.io/apimachinery/pkg/conversion"
runtime "k8s.io/apimachinery/pkg/runtime"
)
func init() {
localSchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*ClusterSelector)(nil), (*search.ClusterSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector(a.(*ClusterSelector), b.(*search.ClusterSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ClusterSelector)(nil), (*ClusterSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector(a.(*search.ClusterSelector), b.(*ClusterSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*FieldSelector)(nil), (*search.FieldSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_FieldSelector_To_search_FieldSelector(a.(*FieldSelector), b.(*search.FieldSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.FieldSelector)(nil), (*FieldSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_FieldSelector_To_v1alpha1_FieldSelector(a.(*search.FieldSelector), b.(*FieldSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ResourceRegistry)(nil), (*search.ResourceRegistry)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(a.(*ResourceRegistry), b.(*search.ResourceRegistry), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ResourceRegistry)(nil), (*ResourceRegistry)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ResourceRegistry_To_v1alpha1_ResourceRegistry(a.(*search.ResourceRegistry), b.(*ResourceRegistry), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ResourceRegistryList)(nil), (*search.ResourceRegistryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ResourceRegistryList_To_search_ResourceRegistryList(a.(*ResourceRegistryList), b.(*search.ResourceRegistryList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ResourceRegistryList)(nil), (*ResourceRegistryList)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList(a.(*search.ResourceRegistryList), b.(*ResourceRegistryList), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ResourceRegistrySpec)(nil), (*search.ResourceRegistrySpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(a.(*ResourceRegistrySpec), b.(*search.ResourceRegistrySpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ResourceRegistrySpec)(nil), (*ResourceRegistrySpec)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(a.(*search.ResourceRegistrySpec), b.(*ResourceRegistrySpec), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ResourceRegistryStatus)(nil), (*search.ResourceRegistryStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus(a.(*ResourceRegistryStatus), b.(*search.ResourceRegistryStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ResourceRegistryStatus)(nil), (*ResourceRegistryStatus)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus(a.(*search.ResourceRegistryStatus), b.(*ResourceRegistryStatus), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*ResourceSelector)(nil), (*search.ResourceSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ResourceSelector_To_search_ResourceSelector(a.(*ResourceSelector), b.(*search.ResourceSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.ResourceSelector)(nil), (*ResourceSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_ResourceSelector_To_v1alpha1_ResourceSelector(a.(*search.ResourceSelector), b.(*ResourceSelector), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*Search)(nil), (*search.Search)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_Search_To_search_Search(a.(*Search), b.(*search.Search), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*search.Search)(nil), (*Search)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_search_Search_To_v1alpha1_Search(a.(*search.Search), b.(*Search), scope)
}); err != nil {
return err
}
return nil
}
func autoConvert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in *ClusterSelector, out *search.ClusterSelector, s conversion.Scope) error {
out.LabelSelector = (*v1.LabelSelector)(unsafe.Pointer(in.LabelSelector))
out.FieldSelector = (*search.FieldSelector)(unsafe.Pointer(in.FieldSelector))
out.ClusterNames = *(*[]string)(unsafe.Pointer(&in.ClusterNames))
out.ExcludeClusters = *(*[]string)(unsafe.Pointer(&in.ExcludeClusters))
return nil
}
// Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector is an autogenerated conversion function.
func Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in *ClusterSelector, out *search.ClusterSelector, s conversion.Scope) error {
return autoConvert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in, out, s)
}
func autoConvert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in *search.ClusterSelector, out *ClusterSelector, s conversion.Scope) error {
out.LabelSelector = (*v1.LabelSelector)(unsafe.Pointer(in.LabelSelector))
out.FieldSelector = (*FieldSelector)(unsafe.Pointer(in.FieldSelector))
out.ClusterNames = *(*[]string)(unsafe.Pointer(&in.ClusterNames))
out.ExcludeClusters = *(*[]string)(unsafe.Pointer(&in.ExcludeClusters))
return nil
}
// Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector is an autogenerated conversion function.
func Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in *search.ClusterSelector, out *ClusterSelector, s conversion.Scope) error {
return autoConvert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in, out, s)
}
func autoConvert_v1alpha1_FieldSelector_To_search_FieldSelector(in *FieldSelector, out *search.FieldSelector, s conversion.Scope) error {
out.MatchExpressions = *(*[]corev1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
return nil
}
// Convert_v1alpha1_FieldSelector_To_search_FieldSelector is an autogenerated conversion function.
func Convert_v1alpha1_FieldSelector_To_search_FieldSelector(in *FieldSelector, out *search.FieldSelector, s conversion.Scope) error {
return autoConvert_v1alpha1_FieldSelector_To_search_FieldSelector(in, out, s)
}
func autoConvert_search_FieldSelector_To_v1alpha1_FieldSelector(in *search.FieldSelector, out *FieldSelector, s conversion.Scope) error {
out.MatchExpressions = *(*[]corev1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
return nil
}
// Convert_search_FieldSelector_To_v1alpha1_FieldSelector is an autogenerated conversion function.
func Convert_search_FieldSelector_To_v1alpha1_FieldSelector(in *search.FieldSelector, out *FieldSelector, s conversion.Scope) error {
return autoConvert_search_FieldSelector_To_v1alpha1_FieldSelector(in, out, s)
}
func autoConvert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(in *ResourceRegistry, out *search.ResourceRegistry, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry is an autogenerated conversion function.
func Convert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(in *ResourceRegistry, out *search.ResourceRegistry, s conversion.Scope) error {
return autoConvert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(in, out, s)
}
func autoConvert_search_ResourceRegistry_To_v1alpha1_ResourceRegistry(in *search.ResourceRegistry, out *ResourceRegistry, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta
if err := Convert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
// Convert_search_ResourceRegistry_To_v1alpha1_ResourceRegistry is an autogenerated conversion function.
func Convert_search_ResourceRegistry_To_v1alpha1_ResourceRegistry(in *search.ResourceRegistry, out *ResourceRegistry, s conversion.Scope) error {
return autoConvert_search_ResourceRegistry_To_v1alpha1_ResourceRegistry(in, out, s)
}
func autoConvert_v1alpha1_ResourceRegistryList_To_search_ResourceRegistryList(in *ResourceRegistryList, out *search.ResourceRegistryList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]search.ResourceRegistry)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_v1alpha1_ResourceRegistryList_To_search_ResourceRegistryList is an autogenerated conversion function.
func Convert_v1alpha1_ResourceRegistryList_To_search_ResourceRegistryList(in *ResourceRegistryList, out *search.ResourceRegistryList, s conversion.Scope) error {
return autoConvert_v1alpha1_ResourceRegistryList_To_search_ResourceRegistryList(in, out, s)
}
func autoConvert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList(in *search.ResourceRegistryList, out *ResourceRegistryList, s conversion.Scope) error {
out.ListMeta = in.ListMeta
out.Items = *(*[]ResourceRegistry)(unsafe.Pointer(&in.Items))
return nil
}
// Convert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList is an autogenerated conversion function.
func Convert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList(in *search.ResourceRegistryList, out *ResourceRegistryList, s conversion.Scope) error {
return autoConvert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList(in, out, s)
}
func autoConvert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(in *ResourceRegistrySpec, out *search.ResourceRegistrySpec, s conversion.Scope) error {
out.ClusterSelectors = *(*[]search.ClusterSelector)(unsafe.Pointer(&in.ClusterSelectors))
out.ResourceSelectors = *(*[]search.ResourceSelector)(unsafe.Pointer(&in.ResourceSelectors))
out.StatusUpdatePeriodSeconds = in.StatusUpdatePeriodSeconds
return nil
}
// Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec is an autogenerated conversion function.
func Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(in *ResourceRegistrySpec, out *search.ResourceRegistrySpec, s conversion.Scope) error {
return autoConvert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(in, out, s)
}
func autoConvert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(in *search.ResourceRegistrySpec, out *ResourceRegistrySpec, s conversion.Scope) error {
out.ClusterSelectors = *(*[]ClusterSelector)(unsafe.Pointer(&in.ClusterSelectors))
out.ResourceSelectors = *(*[]ResourceSelector)(unsafe.Pointer(&in.ResourceSelectors))
out.StatusUpdatePeriodSeconds = in.StatusUpdatePeriodSeconds
return nil
}
// Convert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec is an autogenerated conversion function.
func Convert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(in *search.ResourceRegistrySpec, out *ResourceRegistrySpec, s conversion.Scope) error {
return autoConvert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(in, out, s)
}
func autoConvert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus(in *ResourceRegistryStatus, out *search.ResourceRegistryStatus, s conversion.Scope) error {
out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus is an autogenerated conversion function.
func Convert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus(in *ResourceRegistryStatus, out *search.ResourceRegistryStatus, s conversion.Scope) error {
return autoConvert_v1alpha1_ResourceRegistryStatus_To_search_ResourceRegistryStatus(in, out, s)
}
func autoConvert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus(in *search.ResourceRegistryStatus, out *ResourceRegistryStatus, s conversion.Scope) error {
out.Conditions = *(*[]v1.Condition)(unsafe.Pointer(&in.Conditions))
return nil
}
// Convert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus is an autogenerated conversion function.
func Convert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus(in *search.ResourceRegistryStatus, out *ResourceRegistryStatus, s conversion.Scope) error {
return autoConvert_search_ResourceRegistryStatus_To_v1alpha1_ResourceRegistryStatus(in, out, s)
}
func autoConvert_v1alpha1_ResourceSelector_To_search_ResourceSelector(in *ResourceSelector, out *search.ResourceSelector, s conversion.Scope) error {
out.APIVersion = in.APIVersion
out.Kind = in.Kind
out.Namespace = in.Namespace
return nil
}
// Convert_v1alpha1_ResourceSelector_To_search_ResourceSelector is an autogenerated conversion function.
func Convert_v1alpha1_ResourceSelector_To_search_ResourceSelector(in *ResourceSelector, out *search.ResourceSelector, s conversion.Scope) error {
return autoConvert_v1alpha1_ResourceSelector_To_search_ResourceSelector(in, out, s)
}
func autoConvert_search_ResourceSelector_To_v1alpha1_ResourceSelector(in *search.ResourceSelector, out *ResourceSelector, s conversion.Scope) error {
out.APIVersion = in.APIVersion
out.Kind = in.Kind
out.Namespace = in.Namespace
return nil
}
// Convert_search_ResourceSelector_To_v1alpha1_ResourceSelector is an autogenerated conversion function.
func Convert_search_ResourceSelector_To_v1alpha1_ResourceSelector(in *search.ResourceSelector, out *ResourceSelector, s conversion.Scope) error {
return autoConvert_search_ResourceSelector_To_v1alpha1_ResourceSelector(in, out, s)
}
func autoConvert_v1alpha1_Search_To_search_Search(in *Search, out *search.Search, s conversion.Scope) error {
return nil
}
// Convert_v1alpha1_Search_To_search_Search is an autogenerated conversion function.
func Convert_v1alpha1_Search_To_search_Search(in *Search, out *search.Search, s conversion.Scope) error {
return autoConvert_v1alpha1_Search_To_search_Search(in, out, s)
}
func autoConvert_search_Search_To_v1alpha1_Search(in *search.Search, out *Search, s conversion.Scope) error {
return nil
}
// Convert_search_Search_To_v1alpha1_Search is an autogenerated conversion function.
func Convert_search_Search_To_v1alpha1_Search(in *search.Search, out *Search, s conversion.Scope) error {
return autoConvert_search_Search_To_v1alpha1_Search(in, out, s)
}

View File

@ -197,3 +197,28 @@ func (in *ResourceSelector) DeepCopy() *ResourceSelector {
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Search) DeepCopyInto(out *Search) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Search.
func (in *Search) DeepCopy() *Search {
if in == nil {
return nil
}
out := new(Search)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Search) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@ -44,6 +44,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&ResourceRegistry{},
&ResourceRegistryList{},
&Search{},
)
// AddToGroupVersion allows the serialization of client types like ListOptions.
v1.AddToGroupVersion(scheme, SchemeGroupVersion)

View File

@ -0,0 +1,224 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
// Code generated by deepcopy-gen. DO NOT EDIT.
package search
import (
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) {
*out = *in
if in.LabelSelector != nil {
in, out := &in.LabelSelector, &out.LabelSelector
*out = new(v1.LabelSelector)
(*in).DeepCopyInto(*out)
}
if in.FieldSelector != nil {
in, out := &in.FieldSelector, &out.FieldSelector
*out = new(FieldSelector)
(*in).DeepCopyInto(*out)
}
if in.ClusterNames != nil {
in, out := &in.ClusterNames, &out.ClusterNames
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.ExcludeClusters != nil {
in, out := &in.ExcludeClusters, &out.ExcludeClusters
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector.
func (in *ClusterSelector) DeepCopy() *ClusterSelector {
if in == nil {
return nil
}
out := new(ClusterSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FieldSelector) DeepCopyInto(out *FieldSelector) {
*out = *in
if in.MatchExpressions != nil {
in, out := &in.MatchExpressions, &out.MatchExpressions
*out = make([]corev1.NodeSelectorRequirement, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldSelector.
func (in *FieldSelector) DeepCopy() *FieldSelector {
if in == nil {
return nil
}
out := new(FieldSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceRegistry) DeepCopyInto(out *ResourceRegistry) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRegistry.
func (in *ResourceRegistry) DeepCopy() *ResourceRegistry {
if in == nil {
return nil
}
out := new(ResourceRegistry)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ResourceRegistry) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceRegistryList) DeepCopyInto(out *ResourceRegistryList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]ResourceRegistry, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRegistryList.
func (in *ResourceRegistryList) DeepCopy() *ResourceRegistryList {
if in == nil {
return nil
}
out := new(ResourceRegistryList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ResourceRegistryList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceRegistrySpec) DeepCopyInto(out *ResourceRegistrySpec) {
*out = *in
if in.ClusterSelectors != nil {
in, out := &in.ClusterSelectors, &out.ClusterSelectors
*out = make([]ClusterSelector, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.ResourceSelectors != nil {
in, out := &in.ResourceSelectors, &out.ResourceSelectors
*out = make([]ResourceSelector, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRegistrySpec.
func (in *ResourceRegistrySpec) DeepCopy() *ResourceRegistrySpec {
if in == nil {
return nil
}
out := new(ResourceRegistrySpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceRegistryStatus) DeepCopyInto(out *ResourceRegistryStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRegistryStatus.
func (in *ResourceRegistryStatus) DeepCopy() *ResourceRegistryStatus {
if in == nil {
return nil
}
out := new(ResourceRegistryStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceSelector) DeepCopyInto(out *ResourceSelector) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceSelector.
func (in *ResourceSelector) DeepCopy() *ResourceSelector {
if in == nil {
return nil
}
out := new(ResourceSelector)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Search) DeepCopyInto(out *Search) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Search.
func (in *Search) DeepCopy() *Search {
if in == nil {
return nil
}
out := new(Search)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *Search) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@ -17,7 +17,6 @@ import (
// FakeResourceRegistries implements ResourceRegistryInterface
type FakeResourceRegistries struct {
Fake *FakeSearchV1alpha1
ns string
}
var resourceregistriesResource = schema.GroupVersionResource{Group: "search.karmada.io", Version: "v1alpha1", Resource: "resourceregistries"}
@ -27,8 +26,7 @@ var resourceregistriesKind = schema.GroupVersionKind{Group: "search.karmada.io",
// Get takes name of the resourceRegistry, and returns the corresponding resourceRegistry object, and an error if there is any.
func (c *FakeResourceRegistries) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceRegistry, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(resourceregistriesResource, c.ns, name), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootGetAction(resourceregistriesResource, name), &v1alpha1.ResourceRegistry{})
if obj == nil {
return nil, err
}
@ -38,8 +36,7 @@ func (c *FakeResourceRegistries) Get(ctx context.Context, name string, options v
// List takes label and field selectors, and returns the list of ResourceRegistries that match those selectors.
func (c *FakeResourceRegistries) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ResourceRegistryList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(resourceregistriesResource, resourceregistriesKind, c.ns, opts), &v1alpha1.ResourceRegistryList{})
Invokes(testing.NewRootListAction(resourceregistriesResource, resourceregistriesKind, opts), &v1alpha1.ResourceRegistryList{})
if obj == nil {
return nil, err
}
@ -60,15 +57,13 @@ func (c *FakeResourceRegistries) List(ctx context.Context, opts v1.ListOptions)
// Watch returns a watch.Interface that watches the requested resourceRegistries.
func (c *FakeResourceRegistries) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(resourceregistriesResource, c.ns, opts))
InvokesWatch(testing.NewRootWatchAction(resourceregistriesResource, opts))
}
// Create takes the representation of a resourceRegistry and creates it. Returns the server's representation of the resourceRegistry, and an error, if there is any.
func (c *FakeResourceRegistries) Create(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.CreateOptions) (result *v1alpha1.ResourceRegistry, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(resourceregistriesResource, c.ns, resourceRegistry), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootCreateAction(resourceregistriesResource, resourceRegistry), &v1alpha1.ResourceRegistry{})
if obj == nil {
return nil, err
}
@ -78,8 +73,7 @@ func (c *FakeResourceRegistries) Create(ctx context.Context, resourceRegistry *v
// Update takes the representation of a resourceRegistry and updates it. Returns the server's representation of the resourceRegistry, and an error, if there is any.
func (c *FakeResourceRegistries) Update(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.UpdateOptions) (result *v1alpha1.ResourceRegistry, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(resourceregistriesResource, c.ns, resourceRegistry), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootUpdateAction(resourceregistriesResource, resourceRegistry), &v1alpha1.ResourceRegistry{})
if obj == nil {
return nil, err
}
@ -90,8 +84,7 @@ func (c *FakeResourceRegistries) Update(ctx context.Context, resourceRegistry *v
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeResourceRegistries) UpdateStatus(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.UpdateOptions) (*v1alpha1.ResourceRegistry, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(resourceregistriesResource, "status", c.ns, resourceRegistry), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootUpdateSubresourceAction(resourceregistriesResource, "status", resourceRegistry), &v1alpha1.ResourceRegistry{})
if obj == nil {
return nil, err
}
@ -101,14 +94,13 @@ func (c *FakeResourceRegistries) UpdateStatus(ctx context.Context, resourceRegis
// Delete takes name of the resourceRegistry and deletes it. Returns an error if one occurs.
func (c *FakeResourceRegistries) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteActionWithOptions(resourceregistriesResource, c.ns, name, opts), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootDeleteActionWithOptions(resourceregistriesResource, name, opts), &v1alpha1.ResourceRegistry{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeResourceRegistries) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(resourceregistriesResource, c.ns, listOpts)
action := testing.NewRootDeleteCollectionAction(resourceregistriesResource, listOpts)
_, err := c.Fake.Invokes(action, &v1alpha1.ResourceRegistryList{})
return err
@ -117,8 +109,7 @@ func (c *FakeResourceRegistries) DeleteCollection(ctx context.Context, opts v1.D
// Patch applies the patch and returns the patched resourceRegistry.
func (c *FakeResourceRegistries) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceRegistry, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(resourceregistriesResource, c.ns, name, pt, data, subresources...), &v1alpha1.ResourceRegistry{})
Invokes(testing.NewRootPatchSubresourceAction(resourceregistriesResource, name, pt, data, subresources...), &v1alpha1.ResourceRegistry{})
if obj == nil {
return nil, err
}

View File

@ -12,8 +12,8 @@ type FakeSearchV1alpha1 struct {
*testing.Fake
}
func (c *FakeSearchV1alpha1) ResourceRegistries(namespace string) v1alpha1.ResourceRegistryInterface {
return &FakeResourceRegistries{c, namespace}
func (c *FakeSearchV1alpha1) ResourceRegistries() v1alpha1.ResourceRegistryInterface {
return &FakeResourceRegistries{c}
}
// RESTClient returns a RESTClient that is used to communicate

View File

@ -17,7 +17,7 @@ import (
// ResourceRegistriesGetter has a method to return a ResourceRegistryInterface.
// A group's client should implement this interface.
type ResourceRegistriesGetter interface {
ResourceRegistries(namespace string) ResourceRegistryInterface
ResourceRegistries() ResourceRegistryInterface
}
// ResourceRegistryInterface has methods to work with ResourceRegistry resources.
@ -37,14 +37,12 @@ type ResourceRegistryInterface interface {
// resourceRegistries implements ResourceRegistryInterface
type resourceRegistries struct {
client rest.Interface
ns string
}
// newResourceRegistries returns a ResourceRegistries
func newResourceRegistries(c *SearchV1alpha1Client, namespace string) *resourceRegistries {
func newResourceRegistries(c *SearchV1alpha1Client) *resourceRegistries {
return &resourceRegistries{
client: c.RESTClient(),
ns: namespace,
}
}
@ -52,7 +50,6 @@ func newResourceRegistries(c *SearchV1alpha1Client, namespace string) *resourceR
func (c *resourceRegistries) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ResourceRegistry, err error) {
result = &v1alpha1.ResourceRegistry{}
err = c.client.Get().
Namespace(c.ns).
Resource("resourceregistries").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
@ -69,7 +66,6 @@ func (c *resourceRegistries) List(ctx context.Context, opts v1.ListOptions) (res
}
result = &v1alpha1.ResourceRegistryList{}
err = c.client.Get().
Namespace(c.ns).
Resource("resourceregistries").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
@ -86,7 +82,6 @@ func (c *resourceRegistries) Watch(ctx context.Context, opts v1.ListOptions) (wa
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("resourceregistries").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
@ -97,7 +92,6 @@ func (c *resourceRegistries) Watch(ctx context.Context, opts v1.ListOptions) (wa
func (c *resourceRegistries) Create(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.CreateOptions) (result *v1alpha1.ResourceRegistry, err error) {
result = &v1alpha1.ResourceRegistry{}
err = c.client.Post().
Namespace(c.ns).
Resource("resourceregistries").
VersionedParams(&opts, scheme.ParameterCodec).
Body(resourceRegistry).
@ -110,7 +104,6 @@ func (c *resourceRegistries) Create(ctx context.Context, resourceRegistry *v1alp
func (c *resourceRegistries) Update(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.UpdateOptions) (result *v1alpha1.ResourceRegistry, err error) {
result = &v1alpha1.ResourceRegistry{}
err = c.client.Put().
Namespace(c.ns).
Resource("resourceregistries").
Name(resourceRegistry.Name).
VersionedParams(&opts, scheme.ParameterCodec).
@ -125,7 +118,6 @@ func (c *resourceRegistries) Update(ctx context.Context, resourceRegistry *v1alp
func (c *resourceRegistries) UpdateStatus(ctx context.Context, resourceRegistry *v1alpha1.ResourceRegistry, opts v1.UpdateOptions) (result *v1alpha1.ResourceRegistry, err error) {
result = &v1alpha1.ResourceRegistry{}
err = c.client.Put().
Namespace(c.ns).
Resource("resourceregistries").
Name(resourceRegistry.Name).
SubResource("status").
@ -139,7 +131,6 @@ func (c *resourceRegistries) UpdateStatus(ctx context.Context, resourceRegistry
// Delete takes name of the resourceRegistry and deletes it. Returns an error if one occurs.
func (c *resourceRegistries) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("resourceregistries").
Name(name).
Body(&opts).
@ -154,7 +145,6 @@ func (c *resourceRegistries) DeleteCollection(ctx context.Context, opts v1.Delet
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("resourceregistries").
VersionedParams(&listOpts, scheme.ParameterCodec).
Timeout(timeout).
@ -167,7 +157,6 @@ func (c *resourceRegistries) DeleteCollection(ctx context.Context, opts v1.Delet
func (c *resourceRegistries) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ResourceRegistry, err error) {
result = &v1alpha1.ResourceRegistry{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("resourceregistries").
Name(name).
SubResource(subresources...).

View File

@ -20,8 +20,8 @@ type SearchV1alpha1Client struct {
restClient rest.Interface
}
func (c *SearchV1alpha1Client) ResourceRegistries(namespace string) ResourceRegistryInterface {
return newResourceRegistries(c, namespace)
func (c *SearchV1alpha1Client) ResourceRegistries() ResourceRegistryInterface {
return newResourceRegistries(c)
}
// NewForConfig creates a new SearchV1alpha1Client for the given config.

View File

@ -25,5 +25,5 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
// ResourceRegistries returns a ResourceRegistryInformer.
func (v *version) ResourceRegistries() ResourceRegistryInformer {
return &resourceRegistryInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
return &resourceRegistryInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@ -26,33 +26,32 @@ type ResourceRegistryInformer interface {
type resourceRegistryInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewResourceRegistryInformer constructs a new informer for ResourceRegistry type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewResourceRegistryInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredResourceRegistryInformer(client, namespace, resyncPeriod, indexers, nil)
func NewResourceRegistryInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredResourceRegistryInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredResourceRegistryInformer constructs a new informer for ResourceRegistry type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredResourceRegistryInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
func NewFilteredResourceRegistryInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.SearchV1alpha1().ResourceRegistries(namespace).List(context.TODO(), options)
return client.SearchV1alpha1().ResourceRegistries().List(context.TODO(), options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.SearchV1alpha1().ResourceRegistries(namespace).Watch(context.TODO(), options)
return client.SearchV1alpha1().ResourceRegistries().Watch(context.TODO(), options)
},
},
&searchv1alpha1.ResourceRegistry{},
@ -62,7 +61,7 @@ func NewFilteredResourceRegistryInformer(client versioned.Interface, namespace s
}
func (f *resourceRegistryInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredResourceRegistryInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
return NewFilteredResourceRegistryInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *resourceRegistryInformer) Informer() cache.SharedIndexInformer {

View File

@ -5,7 +5,3 @@ package v1alpha1
// ResourceRegistryListerExpansion allows custom methods to be added to
// ResourceRegistryLister.
type ResourceRegistryListerExpansion interface{}
// ResourceRegistryNamespaceListerExpansion allows custom methods to be added to
// ResourceRegistryNamespaceLister.
type ResourceRegistryNamespaceListerExpansion interface{}

View File

@ -15,8 +15,9 @@ type ResourceRegistryLister interface {
// List lists all ResourceRegistries in the indexer.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha1.ResourceRegistry, err error)
// ResourceRegistries returns an object that can list and get ResourceRegistries.
ResourceRegistries(namespace string) ResourceRegistryNamespaceLister
// Get retrieves the ResourceRegistry from the index for a given name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1alpha1.ResourceRegistry, error)
ResourceRegistryListerExpansion
}
@ -38,41 +39,9 @@ func (s *resourceRegistryLister) List(selector labels.Selector) (ret []*v1alpha1
return ret, err
}
// ResourceRegistries returns an object that can list and get ResourceRegistries.
func (s *resourceRegistryLister) ResourceRegistries(namespace string) ResourceRegistryNamespaceLister {
return resourceRegistryNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// ResourceRegistryNamespaceLister helps list and get ResourceRegistries.
// All objects returned here must be treated as read-only.
type ResourceRegistryNamespaceLister interface {
// List lists all ResourceRegistries in the indexer for a given namespace.
// Objects returned here must be treated as read-only.
List(selector labels.Selector) (ret []*v1alpha1.ResourceRegistry, err error)
// Get retrieves the ResourceRegistry from the indexer for a given namespace and name.
// Objects returned here must be treated as read-only.
Get(name string) (*v1alpha1.ResourceRegistry, error)
ResourceRegistryNamespaceListerExpansion
}
// resourceRegistryNamespaceLister implements the ResourceRegistryNamespaceLister
// interface.
type resourceRegistryNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all ResourceRegistries in the indexer for a given namespace.
func (s resourceRegistryNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ResourceRegistry, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha1.ResourceRegistry))
})
return ret, err
}
// Get retrieves the ResourceRegistry from the indexer for a given namespace and name.
func (s resourceRegistryNamespaceLister) Get(name string) (*v1alpha1.ResourceRegistry, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
// Get retrieves the ResourceRegistry from the index for a given name.
func (s *resourceRegistryLister) Get(name string) (*v1alpha1.ResourceRegistry, error) {
obj, exists, err := s.indexer.GetByKey(name)
if err != nil {
return nil, err
}

View File

@ -76,6 +76,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceRegistrySpec": schema_pkg_apis_search_v1alpha1_ResourceRegistrySpec(ref),
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceRegistryStatus": schema_pkg_apis_search_v1alpha1_ResourceRegistryStatus(ref),
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceSelector": schema_pkg_apis_search_v1alpha1_ResourceSelector(ref),
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.Search": schema_pkg_apis_search_v1alpha1_Search(ref),
"github.com/karmada-io/karmada/pkg/apis/work/v1alpha1.AggregatedStatusItem": schema_pkg_apis_work_v1alpha1_AggregatedStatusItem(ref),
"github.com/karmada-io/karmada/pkg/apis/work/v1alpha1.ClusterResourceBinding": schema_pkg_apis_work_v1alpha1_ClusterResourceBinding(ref),
"github.com/karmada-io/karmada/pkg/apis/work/v1alpha1.ClusterResourceBindingList": schema_pkg_apis_work_v1alpha1_ClusterResourceBindingList(ref),
@ -3280,6 +3281,33 @@ func schema_pkg_apis_search_v1alpha1_ResourceSelector(ref common.ReferenceCallba
}
}
func schema_pkg_apis_search_v1alpha1_Search(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Search define a flag for resource search that do not have actual resources.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"kind": {
SchemaProps: spec.SchemaProps{
Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
Type: []string{"string"},
Format: "",
},
},
"apiVersion": {
SchemaProps: spec.SchemaProps{
Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
Type: []string{"string"},
Format: "",
},
},
},
},
},
}
}
func schema_pkg_apis_work_v1alpha1_AggregatedStatusItem(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{

View File

@ -172,7 +172,7 @@ func getName(str, start, end string) string {
}
func initAPIService(clientSet *kubernetes.Clientset, restConfig *rest.Config, systemNamespace string) error {
// https://github.com/karmada-io/karmada/blob/master/artifacts/deploy/apiservice.yaml
// https://github.com/karmada-io/karmada/blob/master/artifacts/deploy/karmada-aggregated-apiserver-apiservice.yaml
aaService := &corev1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",

View File

@ -0,0 +1,88 @@
package storage
import (
"context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/apiserver/pkg/registry/rest"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
searchapis "github.com/karmada-io/karmada/pkg/apis/search"
searchregistry "github.com/karmada-io/karmada/pkg/registry/search"
)
// ResourceRegistryStorage includes storage for ResourceRegistry and for all the subresources.
type ResourceRegistryStorage struct {
ResourceRegistry *REST
Status *StatusREST
}
// NewResourceRegistryStorage returns a ResourceRegistryStorage object that will work against resourceRegistries.
func NewResourceRegistryStorage(scheme *runtime.Scheme, optsGetter generic.RESTOptionsGetter) (*ResourceRegistryStorage, error) {
strategy := searchregistry.NewStrategy(scheme)
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &searchapis.ResourceRegistry{} },
NewListFunc: func() runtime.Object { return &searchapis.ResourceRegistryList{} },
PredicateFunc: searchregistry.MatchResourceRegistry,
DefaultQualifiedResource: searchapis.Resource("resourceRegistries"),
CreateStrategy: strategy,
UpdateStrategy: strategy,
DeleteStrategy: strategy,
// TODO: define table converter that exposes more than name/creation timestamp
TableConvertor: rest.NewDefaultTableConvertor(searchapis.Resource("resourceRegistries")),
}
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: searchregistry.GetAttrs}
if err := store.CompleteWithOptions(options); err != nil {
return nil, err
}
statusStrategy := searchregistry.NewStatusStrategy(strategy)
statusStore := *store
statusStore.UpdateStrategy = statusStrategy
statusStore.ResetFieldsStrategy = statusStrategy
resourceRegistryRest := &REST{store}
return &ResourceRegistryStorage{
ResourceRegistry: resourceRegistryRest,
Status: &StatusREST{&statusStore},
}, nil
}
// REST implements a RESTStorage for ResourceRegistry.
type REST struct {
*genericregistry.Store
}
// StatusREST implements the REST endpoint for changing the status of a ResourceRegistry.
type StatusREST struct {
store *genericregistry.Store
}
// New returns empty ResourceRegistry.
func (r *StatusREST) New() runtime.Object {
return &searchapis.ResourceRegistry{}
}
// Get retrieves the object from the storage. It is required to support Patch.
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
return r.store.Get(ctx, name, options)
}
// Update alters the status subset of an object.
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
// subresources should never allow create on update.
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false, options)
}
// GetResetFields implements rest.ResetFieldsStrategy
func (r *StatusREST) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
return r.store.GetResetFields()
}

View File

@ -0,0 +1,61 @@
package storage
import (
"context"
"net/http"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
searchapis "github.com/karmada-io/karmada/pkg/apis/search"
)
// SearchREST implements a RESTStorage for search resource.
type SearchREST struct {
kubeClient kubernetes.Interface
// add needed parameters here
}
var _ rest.Scoper = &SearchREST{}
var _ rest.Storage = &SearchREST{}
var _ rest.Connecter = &SearchREST{}
// NewSearchREST returns a RESTStorage object that will work against search.
func NewSearchREST(client kubernetes.Interface) *SearchREST {
return &SearchREST{
kubeClient: client,
}
}
// New return empty Search object.
func (r *SearchREST) New() runtime.Object {
return &searchapis.Search{}
}
// NamespaceScoped returns false because Search is not namespaced.
func (r *SearchREST) NamespaceScoped() bool {
return false
}
// ConnectMethods returns the list of HTTP methods handled by Connect.
func (r *SearchREST) ConnectMethods() []string {
return []string{"GET"}
}
// NewConnectOptions returns an empty options object that will be used to pass options to the Connect method.
func (r *SearchREST) NewConnectOptions() (runtime.Object, bool, string) {
return nil, true, ""
}
// Connect returns a handler for the ES search.
func (r *SearchREST) Connect(ctx context.Context, id string, _ runtime.Object, responder rest.Responder) (http.Handler, error) {
klog.Infof("Prepare for construct handler to connect ES.")
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
// Construct a handler and send the request to the ES.
}), nil
}

View File

@ -0,0 +1,142 @@
package search
import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
searchapis "github.com/karmada-io/karmada/pkg/apis/search"
)
// NewStrategy creates and returns a ResourceRegistry Strategy instance.
func NewStrategy(typer runtime.ObjectTyper) Strategy {
return Strategy{typer, names.SimpleNameGenerator}
}
// GetAttrs returns labels.Set, fields.Set, and error in case the given runtime.Object is not a ResourceRegistry.
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
resourceRegistry, ok := obj.(*searchapis.ResourceRegistry)
if !ok {
return nil, nil, fmt.Errorf("given object is not a ResourceRegistry")
}
return resourceRegistry.ObjectMeta.Labels, SelectableFields(resourceRegistry), nil
}
// MatchResourceRegistry is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchResourceRegistry(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: GetAttrs,
}
}
// SelectableFields returns a field set that represents the object.
func SelectableFields(obj *searchapis.ResourceRegistry) fields.Set {
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, false)
}
// Strategy implements behavior for ResourceRegistry.
type Strategy struct {
runtime.ObjectTyper
names.NameGenerator
}
// NamespaceScoped returns if the object must be in a namespace.
func (Strategy) NamespaceScoped() bool {
return false
}
// GetResetFields returns the set of fields that get reset by the strategy
// and should not be modified by the user.
func (Strategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
return map[fieldpath.APIVersion]*fieldpath.Set{
"search.karmada.io/v1alpha1": fieldpath.NewSet(
fieldpath.MakePathOrDie("status"),
),
}
}
// PrepareForCreate is invoked on create before validation to normalize the object.
func (Strategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
}
// PrepareForUpdate is invoked on update before validation to normalize the object.
func (Strategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
}
// Validate returns an ErrorList with validation errors or nil.
func (Strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
// TODO: add validation for ResourceRegistry
return field.ErrorList{}
}
// WarningsOnCreate returns warnings for the creation of the given object.
func (Strategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return nil }
// AllowCreateOnUpdate returns true if the object can be created by a PUT.
func (Strategy) AllowCreateOnUpdate() bool {
return false
}
// AllowUnconditionalUpdate returns true if the object can be updated
// unconditionally (irrespective of the latest resource version), when
// there is no resource version specified in the object.
func (Strategy) AllowUnconditionalUpdate() bool {
return true
}
// Canonicalize allows an object to be mutated into a canonical form.
func (Strategy) Canonicalize(obj runtime.Object) {
}
// ValidateUpdate is invoked after default fields in the object have been
// filled in before the object is persisted.
func (Strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
// TODO: add validation for ResourceRegistry
return field.ErrorList{}
}
// WarningsOnUpdate returns warnings for the given update.
func (Strategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}
// StatusStrategy implements behavior for ResourceRegistryStatus.
type StatusStrategy struct {
Strategy
}
// NewStatusStrategy creates and returns a StatusStrategy instance.
func NewStatusStrategy(strategy Strategy) StatusStrategy {
return StatusStrategy{strategy}
}
// GetResetFields returns the set of fields that get reset by the strategy
// and should not be modified by the user.
func (StatusStrategy) GetResetFields() map[fieldpath.APIVersion]*fieldpath.Set {
return map[fieldpath.APIVersion]*fieldpath.Set{}
}
// PrepareForUpdate clears fields that are not allowed to be set by end users on update of status
func (StatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
}
// ValidateUpdate is the default update validation for an end user updating status
func (StatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
return field.ErrorList{}
}
// WarningsOnUpdate returns warnings for the given update.
func (StatusStrategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string {
return nil
}

118
pkg/search/apiserver.go Normal file
View File

@ -0,0 +1,118 @@
package search
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/version"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
searchapis "github.com/karmada-io/karmada/pkg/apis/search"
searchinstall "github.com/karmada-io/karmada/pkg/apis/search/install"
searchstorage "github.com/karmada-io/karmada/pkg/registry/search/storage"
)
var (
// Scheme defines methods for serializing and deserializing API objects.
Scheme = runtime.NewScheme()
// Codecs provides methods for retrieving codecs and serializers for specific
// versions and content types.
Codecs = serializer.NewCodecFactory(Scheme)
// ParameterCodec handles versioning of objects that are converted to query parameters.
ParameterCodec = runtime.NewParameterCodec(Scheme)
)
func init() {
searchinstall.Install(Scheme)
// we need to add the options to empty v1
// TODO fix the server code to avoid this
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
// TODO: keep the generic API server from wanting this
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
Scheme.AddUnversionedTypes(unversioned,
&metav1.Status{},
&metav1.APIVersions{},
&metav1.APIGroupList{},
&metav1.APIGroup{},
&metav1.APIResourceList{},
)
}
// ExtraConfig holds custom apiserver config
type ExtraConfig struct {
// Add custom config if necessary.
}
// Config defines the config for the APIServer.
type Config struct {
GenericConfig *genericapiserver.RecommendedConfig
ExtraConfig ExtraConfig
}
// APIServer contains state for karmada-search.
type APIServer struct {
GenericAPIServer *genericapiserver.GenericAPIServer
}
type completedConfig struct {
GenericConfig genericapiserver.CompletedConfig
ExtraConfig *ExtraConfig
}
// CompletedConfig embeds a private pointer that cannot be instantiated outside this package.
type CompletedConfig struct {
*completedConfig
}
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
func (cfg *Config) Complete() CompletedConfig {
c := completedConfig{
cfg.GenericConfig.Complete(),
&cfg.ExtraConfig,
}
c.GenericConfig.Version = &version.Info{
Major: "1",
Minor: "0",
}
return CompletedConfig{&c}
}
func (c completedConfig) New(kubeClient kubernetes.Interface) (*APIServer, error) {
genericServer, err := c.GenericConfig.New("karmada-search", genericapiserver.NewEmptyDelegate())
if err != nil {
return nil, err
}
server := &APIServer{
GenericAPIServer: genericServer,
}
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(searchapis.GroupName, Scheme, ParameterCodec, Codecs)
resourceRegistryStorage, err := searchstorage.NewResourceRegistryStorage(Scheme, c.GenericConfig.RESTOptionsGetter)
if err != nil {
klog.Errorf("unable to create REST storage for a resource due to %v, will die", err)
return nil, err
}
searchREST := searchstorage.NewSearchREST(kubeClient)
v1alpha1search := map[string]rest.Storage{}
v1alpha1search["resourceRegistry"] = resourceRegistryStorage.ResourceRegistry
v1alpha1search["resourceRegistry/status"] = resourceRegistryStorage.Status
v1alpha1search["search"] = searchREST
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1search
if err = server.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
return nil, err
}
return server, nil
}