karmada/pkg/resourceinterpreter/default/native/dependencies.go

182 lines
6.5 KiB
Go

/*
Copyright 2022 The Karmada Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package native
import (
"fmt"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
mcsv1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1"
configv1alpha1 "github.com/karmada-io/karmada/pkg/apis/config/v1alpha1"
"github.com/karmada-io/karmada/pkg/util"
"github.com/karmada-io/karmada/pkg/util/helper"
"github.com/karmada-io/karmada/pkg/util/lifted"
"github.com/karmada-io/karmada/pkg/util/names"
)
type dependenciesInterpreter func(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error)
func getAllDefaultDependenciesInterpreter() map[schema.GroupVersionKind]dependenciesInterpreter {
s := make(map[schema.GroupVersionKind]dependenciesInterpreter)
s[appsv1.SchemeGroupVersion.WithKind(util.DeploymentKind)] = getDeploymentDependencies
s[batchv1.SchemeGroupVersion.WithKind(util.JobKind)] = getJobDependencies
s[batchv1.SchemeGroupVersion.WithKind(util.CronJobKind)] = getCronJobDependencies
s[corev1.SchemeGroupVersion.WithKind(util.PodKind)] = getPodDependencies
s[appsv1.SchemeGroupVersion.WithKind(util.DaemonSetKind)] = getDaemonSetDependencies
s[appsv1.SchemeGroupVersion.WithKind(util.StatefulSetKind)] = getStatefulSetDependencies
s[networkingv1.SchemeGroupVersion.WithKind(util.IngressKind)] = getIngressDependencies
s[mcsv1alpha1.SchemeGroupVersion.WithKind(util.ServiceImportKind)] = getServiceImportDependencies
return s
}
func getDeploymentDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
deploymentObj := &appsv1.Deployment{}
if err := helper.ConvertToTypedObject(object, deploymentObj); err != nil {
return nil, fmt.Errorf("failed to convert Deployment from unstructured object: %v", err)
}
podObj, err := lifted.GetPodFromTemplate(&deploymentObj.Spec.Template, deploymentObj, nil)
if err != nil {
return nil, err
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
jobObj := &batchv1.Job{}
err := helper.ConvertToTypedObject(object, jobObj)
if err != nil {
return nil, fmt.Errorf("failed to convert Job from unstructured object: %v", err)
}
podObj, err := lifted.GetPodFromTemplate(&jobObj.Spec.Template, jobObj, nil)
if err != nil {
return nil, err
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getCronJobDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
cronjobObj := &batchv1.CronJob{}
err := helper.ConvertToTypedObject(object, cronjobObj)
if err != nil {
return nil, fmt.Errorf("failed to convert CronJob from unstructured object: %v", err)
}
podObj, err := lifted.GetPodFromTemplate(&cronjobObj.Spec.JobTemplate.Spec.Template, cronjobObj, nil)
if err != nil {
return nil, err
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getPodDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
podObj := &corev1.Pod{}
err := helper.ConvertToTypedObject(object, podObj)
if err != nil {
return nil, fmt.Errorf("failed to convert Pod from unstructured object: %v", err)
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getDaemonSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
daemonSetObj := &appsv1.DaemonSet{}
err := helper.ConvertToTypedObject(object, daemonSetObj)
if err != nil {
return nil, fmt.Errorf("failed to convert DaemonSet from unstructured object: %v", err)
}
podObj, err := lifted.GetPodFromTemplate(&daemonSetObj.Spec.Template, daemonSetObj, nil)
if err != nil {
return nil, err
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getStatefulSetDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
statefulSetObj := &appsv1.StatefulSet{}
err := helper.ConvertToTypedObject(object, statefulSetObj)
if err != nil {
return nil, fmt.Errorf("failed to convert StatefulSet from unstructured object: %v", err)
}
podObj, err := lifted.GetPodFromTemplate(&statefulSetObj.Spec.Template, statefulSetObj, nil)
if err != nil {
return nil, err
}
return helper.GetDependenciesFromPodTemplate(podObj)
}
func getIngressDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
ingressObj := &networkingv1.Ingress{}
err := helper.ConvertToTypedObject(object, ingressObj)
if err != nil {
return nil, fmt.Errorf("failed to convert Ingress from unstructured object: %v", err)
}
var dependentObjectRefs []configv1alpha1.DependentObjectReference
for _, tls := range ingressObj.Spec.TLS {
dependentObjectRefs = append(dependentObjectRefs, configv1alpha1.DependentObjectReference{
APIVersion: "v1",
Kind: "Secret",
Namespace: ingressObj.Namespace,
Name: tls.SecretName,
})
}
return dependentObjectRefs, nil
}
func getServiceImportDependencies(object *unstructured.Unstructured) ([]configv1alpha1.DependentObjectReference, error) {
svcImportObj := &mcsv1alpha1.ServiceImport{}
err := helper.ConvertToTypedObject(object, svcImportObj)
if err != nil {
return nil, fmt.Errorf("failed to convert ServiceImport from unstructured object: %v", err)
}
derivedServiceName := names.GenerateDerivedServiceName(svcImportObj.Name)
return []configv1alpha1.DependentObjectReference{
{
APIVersion: "v1",
Kind: util.ServiceKind,
Namespace: svcImportObj.Namespace,
Name: derivedServiceName,
},
{
APIVersion: "discovery.k8s.io/v1",
Kind: util.EndpointSliceKind,
Namespace: svcImportObj.Namespace,
LabelSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
discoveryv1.LabelServiceName: derivedServiceName,
},
},
},
}, nil
}