package bluegreen import ( "context" "fmt" "strings" _ "github.com/golang/mock/mockgen/model" v1 "github.com/kakao/bluegreen/api/v1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) //go:generate go run github.com/golang/mock/mockgen@v1.6.0 -package bluegreen -destination mock.gen.go . Client type Client interface { client.Reader CreateOrUpdateService(ctx context.Context, owner *v1.BlueGreen) error CreateOrUpdateDeployment(ctx context.Context, owner *v1.BlueGreen, phase v1.BlueOrGreen, podSpec corev1.PodSpec) error UpdateStatus(ctx context.Context, bg *v1.BlueGreen) error } var _ Client = &BlueGreenClient{} type BlueGreenClient struct { client.Client } func (r *BlueGreenClient) UpdateStatus(ctx context.Context, bg *v1.BlueGreen) error { return r.Status().Update(ctx, bg) } func (r *BlueGreenClient) CreateOrUpdateDeployment(ctx context.Context, owner *v1.BlueGreen, phase v1.BlueOrGreen, podSpec corev1.PodSpec) error { deploy := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Namespace: owner.Namespace, Name: deploymentName(owner.Name, phase)}} if _, err := ctrl.CreateOrUpdate(ctx, r.Client, deploy, func() error { if err := ctrl.SetControllerReference(owner, deploy, r.Scheme()); err != nil { return err } label := map[string]string{ "app.kubernetes.io/managed-by": "app.demo.kakao.com", "app.kubernetes.io/name": owner.Name, "app.kubernetes.io/phase": string(phase), } deploy.Spec.Selector = &metav1.LabelSelector{MatchLabels: label} deploy.Spec.Template = corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{Labels: label}, Spec: podSpec, } return nil }); err != nil { return err } return nil } func (r *BlueGreenClient) CreateOrUpdateService(ctx context.Context, owner *v1.BlueGreen) error { svc := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Namespace: owner.Namespace, Name: owner.Name}} if _, err := ctrl.CreateOrUpdate(ctx, r.Client, svc, func() error { if err := ctrl.SetControllerReference(owner, svc, r.Scheme()); err != nil { return err } svc.Spec.Ports = []corev1.ServicePort{ {Name: "http", Protocol: corev1.ProtocolTCP, Port: 80}, } svc.Spec.Selector = map[string]string{ "app.kubernetes.io/managed-by": "app.demo.kakao.com", "app.kubernetes.io/name": owner.Name, "app.kubernetes.io/phase": string(owner.Spec.RouteTo), } return nil }, ); err != nil { return err } return nil } func deploymentName(name string, phase v1.BlueOrGreen) string { return fmt.Sprintf("%s-%s", name, strings.ToLower(string(phase))) }