package controllers import ( "strings" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" networkv1 "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/util/intstr" myAppsv1 "mashibing.com/pkg/mashibing-deployment/api/v1" ) var IngressClassName = "nginx" var PathTypePrefix = networkv1.PathTypePrefix func NewDeployment(md *myAppsv1.MsbDeployment) appsv1.Deployment { // 1. 创建基本的deployment // 1.1 创建只含有metadata信息的对象 deploy := newBaseDeployment(md) // 2. 创建附加的对象 // 2.1 在基本的deployment中添加其他的对象 deploy.Spec.Replicas = &md.Spec.Replicas deploy.Spec.Selector = &metav1.LabelSelector{MatchLabels: newLabels(md)} deploy.Spec.Template.ObjectMeta = metav1.ObjectMeta{Labels: newLabels(md)} deploy.Spec.Template.Spec.Containers = []corev1.Container{ newBaseContainer(md), } return deploy } func NewIngress(md *myAppsv1.MsbDeployment) networkv1.Ingress { ig := newBaseIngress(md) ig.Spec.IngressClassName = &IngressClassName ig.Spec.Rules = []networkv1.IngressRule{ newIngressRule(md), } if md.Spec.Expose.Tls { ig.Spec.TLS = []networkv1.IngressTLS{ newIngressTLS(md), } } return ig } func NewService(md *myAppsv1.MsbDeployment) corev1.Service { svc := newBaseService(md) svc.Spec.Selector = newLabels(md) servicePort := newServicePort(md) switch strings.ToLower(md.Spec.Expose.Mode) { case myAppsv1.ModeIngress: svc.Spec.Ports = []corev1.ServicePort{servicePort} case myAppsv1.ModeNodePort: svc.Spec.Type = corev1.ServiceTypeNodePort servicePort.NodePort = md.Spec.Expose.NodePort svc.Spec.Ports = []corev1.ServicePort{servicePort} default: return corev1.Service{} } return svc } // NewIssuer 实现创建issuer资源对象 func NewIssuer(md *myAppsv1.MsbDeployment) (*unstructured.Unstructured, error) { if md.Spec.Expose.Mode != myAppsv1.ModeIngress || !md.Spec.Expose.Tls { return nil, nil } // Sample //apiVersion: cert-manager.io/v1 //kind: Issuer //metadata: // name: selfsigned-issuer //spec: // selfSigned: {} return &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Issuer", "metadata": map[string]interface{}{ "name": md.Name, "namespace": md.Namespace, }, "spec": map[string]interface{}{ "selfSigned": map[string]interface{}{}, }, }, }, nil } // NewCert 实现创建certificate资源 func NewCert(md *myAppsv1.MsbDeployment) (*unstructured.Unstructured, error) { if md.Spec.Expose.Mode != myAppsv1.ModeIngress || !md.Spec.Expose.Tls { return nil, nil } // Sample //apiVersion: cert-manager.io/v1 //kind: Certificate //metadata: // name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml // namespace: system //spec: // dnsNames: // - // issuerRef: // kind: Issuer // name: selfsigned-issuer // secretName: webhook-server-cert return &unstructured.Unstructured{ Object: map[string]interface{}{ "apiVersion": "cert-manager.io/v1", "kind": "Certificate", "metadata": map[string]interface{}{ "name": md.Name, "namespace": md.Namespace, }, "spec": map[string]interface{}{ "dnsNames": []interface{}{ md.Spec.Expose.IngressDomain, }, "issuerRef": map[string]interface{}{ "kind": "Issuer", "name": md.Name, }, "secretName": md.Name, }, }, }, nil } func newBaseContainer(md *myAppsv1.MsbDeployment) corev1.Container { c := corev1.Container{ Name: md.Name, Image: md.Spec.Image, Ports: []corev1.ContainerPort{ { ContainerPort: md.Spec.Port, }, }, } if len(md.Spec.StartCmd) != 0 { c.Command = md.Spec.StartCmd } if len(md.Spec.Args) != 0 { c.Args = md.Spec.Args } if len(md.Spec.Environments) != 0 { c.Env = md.Spec.Environments } return c } func newBaseDeployment(md *myAppsv1.MsbDeployment) appsv1.Deployment { return appsv1.Deployment{ TypeMeta: metav1.TypeMeta{ Kind: "Deployment", APIVersion: "apps/v1", }, ObjectMeta: metav1.ObjectMeta{ Name: md.Name, Namespace: md.Namespace, Labels: newLabels(md), }, } } func newServicePort(md *myAppsv1.MsbDeployment) corev1.ServicePort { return corev1.ServicePort{ Protocol: corev1.ProtocolTCP, Port: md.Spec.Expose.ServicePort, TargetPort: intstr.IntOrString{ Type: intstr.Int, IntVal: md.Spec.Port, }, } } func newBaseService(md *myAppsv1.MsbDeployment) corev1.Service { return corev1.Service{ TypeMeta: metav1.TypeMeta{ Kind: "Service", APIVersion: "v1", }, ObjectMeta: metav1.ObjectMeta{ Name: md.Name, Namespace: md.Namespace, }, } } func newIngressTLS(md *myAppsv1.MsbDeployment) networkv1.IngressTLS { return networkv1.IngressTLS{ Hosts: []string{md.Spec.Expose.IngressDomain}, SecretName: md.Name, } } func newIngressRule(md *myAppsv1.MsbDeployment) networkv1.IngressRule { return networkv1.IngressRule{ Host: md.Spec.Expose.IngressDomain, IngressRuleValue: networkv1.IngressRuleValue{ HTTP: &networkv1.HTTPIngressRuleValue{ Paths: []networkv1.HTTPIngressPath{ { PathType: &PathTypePrefix, Path: "/", Backend: networkv1.IngressBackend{ Service: &networkv1.IngressServiceBackend{ Name: md.Name, Port: networkv1.ServiceBackendPort{ Number: md.Spec.Expose.ServicePort, }, }, }, }, }, }, }, } } func newBaseIngress(md *myAppsv1.MsbDeployment) networkv1.Ingress { return networkv1.Ingress{ TypeMeta: metav1.TypeMeta{ Kind: "Ingress", APIVersion: "networking.k8s.io/v1", }, ObjectMeta: metav1.ObjectMeta{ Name: md.Name, Namespace: md.Namespace, }, } } func newLabels(md *myAppsv1.MsbDeployment) map[string]string { return map[string]string{"app": md.Name} }