Skip to content

Commit

Permalink
Merge pull request #49 from kerthcet/cleanup/code-refactor
Browse files Browse the repository at this point in the history
Fix: build image error
  • Loading branch information
k8s-ci-robot authored Mar 11, 2024
2 parents e9eda44 + d029b10 commit 0e5b557
Show file tree
Hide file tree
Showing 5 changed files with 315 additions and 280 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ RUN go mod download
# Copy the go source
COPY cmd/main.go cmd/main.go
COPY api/ api/
COPY pkg/controller/ pkg/controller/
COPY pkg/controllers/ pkg/controllers/
COPY pkg/cert/ pkg/cert/
COPY pkg/webhook/ pkg/webhook/
COPY pkg/webhooks/ pkg/webhooks/
COPY pkg/utils pkg/utils

# Build
Expand Down
115 changes: 115 additions & 0 deletions pkg/controllers/leaderworkerset_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ package controllers
import (
"context"
"fmt"
"strconv"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
appsapplyv1 "k8s.io/client-go/applyconfigurations/apps/v1"
coreapplyv1 "k8s.io/client-go/applyconfigurations/core/v1"
metaapplyv1 "k8s.io/client-go/applyconfigurations/meta/v1"
"k8s.io/client-go/tools/record"
"k8s.io/klog/v2"
"k8s.io/utils/pointer"
Expand Down Expand Up @@ -298,3 +302,114 @@ func (r *LeaderWorkerSetReconciler) updateStatus(ctx context.Context, lws *leade
}
return nil
}

// constructLeaderStatefulSetApplyConfiguration constructs the apply configuration for the leader StatefulSet
func constructLeaderStatefulSetApplyConfiguration(lws *leaderworkerset.LeaderWorkerSet) (*appsapplyv1.StatefulSetApplyConfiguration, error) {
var podTemplateSpec corev1.PodTemplateSpec
if lws.Spec.LeaderWorkerTemplate.LeaderTemplate != nil {
podTemplateSpec = *lws.Spec.LeaderWorkerTemplate.LeaderTemplate.DeepCopy()
} else {
podTemplateSpec = *lws.Spec.LeaderWorkerTemplate.WorkerTemplate.DeepCopy()
}
// construct pod template spec configuration
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&podTemplateSpec)
if err != nil {
return nil, err
}
var podTemplateApplyConfiguration coreapplyv1.PodTemplateSpecApplyConfiguration
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj, &podTemplateApplyConfiguration)
if err != nil {
return nil, err
}
podTemplateApplyConfiguration.WithLabels(map[string]string{
leaderworkerset.WorkerIndexLabelKey: "0",
leaderworkerset.SetNameLabelKey: lws.Name,
})
podAnnotations := make(map[string]string)
podAnnotations[leaderworkerset.SizeAnnotationKey] = strconv.Itoa(int(*lws.Spec.LeaderWorkerTemplate.Size))
if lws.Annotations[leaderworkerset.ExclusiveKeyAnnotationKey] != "" {
podAnnotations[leaderworkerset.ExclusiveKeyAnnotationKey] = lws.Annotations[leaderworkerset.ExclusiveKeyAnnotationKey]
}
podTemplateApplyConfiguration.WithAnnotations(podAnnotations)
// construct statefulset apply configuration
statefulSetConfig := appsapplyv1.StatefulSet(lws.Name, lws.Namespace).
WithSpec(appsapplyv1.StatefulSetSpec().
WithServiceName(lws.Name).
WithReplicas(*lws.Spec.Replicas).
WithPodManagementPolicy(appsv1.ParallelPodManagement).
WithTemplate(&podTemplateApplyConfiguration).
WithServiceName(lws.Name).
WithSelector(metaapplyv1.LabelSelector().
WithMatchLabels(map[string]string{
leaderworkerset.SetNameLabelKey: lws.Name,
leaderworkerset.WorkerIndexLabelKey: "0",
}))).
WithLabels(map[string]string{
leaderworkerset.SetNameLabelKey: lws.Name,
})
return statefulSetConfig, nil
}

func makeCondition(available bool) metav1.Condition {
condtype := string(leaderworkerset.LeaderWorkerSetProgressing)
reason := "GroupsAreProgressing"
message := "Creating resources"

if available {
condtype = string(leaderworkerset.LeaderWorkerSetAvailable)
reason = "AllGroupsReady"
message = "all replicas are ready"
}

condition := metav1.Condition{
Type: condtype,
Status: metav1.ConditionStatus(corev1.ConditionTrue),
LastTransitionTime: metav1.Now(),
Reason: reason,
Message: message,
}
return condition
}

func setCondition(lws *leaderworkerset.LeaderWorkerSet, newCondition metav1.Condition) bool {
newCondition.LastTransitionTime = metav1.Now()
found := false
shouldUpdate := false

// Precondition: newCondition has status true.
for i, curCondition := range lws.Status.Conditions {
if newCondition.Type == curCondition.Type {
if newCondition.Status != curCondition.Status {
// the conditions match but one is true and one is false. Update the stored condition
// with the new condition.
lws.Status.Conditions[i] = newCondition
shouldUpdate = true
}
// if both are true or both are false, do nothing.
found = true
} else {
// if the conditions are not of the same type, do nothing unless one is Progressing and one is
// Available and both are true. Must be mutually exclusive.
if exclusiveConditionTypes(curCondition, newCondition) &&
(newCondition.Status == metav1.ConditionTrue) && (curCondition.Status == metav1.ConditionTrue) {
// Progressing is true and Available is true. Prevent this.
lws.Status.Conditions[i].Status = metav1.ConditionFalse
shouldUpdate = true
}
}
}
// condition doesn't exist, update only if the status is true
if newCondition.Status == metav1.ConditionTrue && !found {
lws.Status.Conditions = append(lws.Status.Conditions, newCondition)
shouldUpdate = true
}
return shouldUpdate
}

func exclusiveConditionTypes(condition1 metav1.Condition, condition2 metav1.Condition) bool {
if (condition1.Type == string(leaderworkerset.LeaderWorkerSetAvailable) && condition2.Type == string(leaderworkerset.LeaderWorkerSetProgressing)) ||
(condition1.Type == string(leaderworkerset.LeaderWorkerSetProgressing) && condition2.Type == string(leaderworkerset.LeaderWorkerSetAvailable)) {
return true
}
return false
}
167 changes: 0 additions & 167 deletions pkg/controllers/leaderworkerset_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
appsapplyv1 "k8s.io/client-go/applyconfigurations/apps/v1"
coreapplyv1 "k8s.io/client-go/applyconfigurations/core/v1"
metaapplyv1 "k8s.io/client-go/applyconfigurations/meta/v1"
Expand Down Expand Up @@ -217,172 +216,6 @@ func TestLeaderStatefulSetApplyConfig(t *testing.T) {
}
}

func TestConstructWorkerStatefulSetApplyConfiguration(t *testing.T) {
tests := []struct {
name string
pod *corev1.Pod
lws *leaderworkerset.LeaderWorkerSet
wantStatefulSetConfig *appsapplyv1.StatefulSetApplyConfiguration
}{
{
name: "1 replica, size 1, exclusive placement disabled",
pod: &corev1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: "test-sample",
Namespace: "default",
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/worker-index": "0",
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
},
lws: testutils.BuildBasicLeaderWorkerSet("test-sample", "default").
Replica(1).
WorkerTemplateSpec(testutils.MakeWorkerPodSpec()).
Size(1).Obj(),
wantStatefulSetConfig: &appsapplyv1.StatefulSetApplyConfiguration{
TypeMetaApplyConfiguration: metaapplyv1.TypeMetaApplyConfiguration{
Kind: ptr.To[string]("StatefulSet"),
APIVersion: ptr.To[string]("apps/v1"),
},
ObjectMetaApplyConfiguration: &metaapplyv1.ObjectMetaApplyConfiguration{
Name: ptr.To[string]("test-sample"),
Namespace: ptr.To[string]("default"),
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
Spec: &appsapplyv1.StatefulSetSpecApplyConfiguration{
Replicas: ptr.To[int32](0),
Selector: &metaapplyv1.LabelSelectorApplyConfiguration{
MatchLabels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
Template: &coreapplyv1.PodTemplateSpecApplyConfiguration{
ObjectMetaApplyConfiguration: &metaapplyv1.ObjectMetaApplyConfiguration{
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
Annotations: map[string]string{
"leaderworkerset.sigs.k8s.io/size": "1",
"leaderworkerset.sigs.k8s.io/leader-name": "test-sample",
},
},
Spec: &coreapplyv1.PodSpecApplyConfiguration{
Containers: []coreapplyv1.ContainerApplyConfiguration{
{
Name: ptr.To[string]("leader"),
Image: ptr.To[string]("nginx:1.14.2"),
Ports: []coreapplyv1.ContainerPortApplyConfiguration{{ContainerPort: ptr.To[int32](8080), Protocol: ptr.To[corev1.Protocol](corev1.ProtocolTCP)}},
Resources: &coreapplyv1.ResourceRequirementsApplyConfiguration{},
},
},
},
},
Ordinals: &appsapplyv1.StatefulSetOrdinalsApplyConfiguration{Start: ptr.To[int32](1)},
ServiceName: ptr.To[string]("test-sample"),
PodManagementPolicy: ptr.To[appsv1.PodManagementPolicyType](appsv1.ParallelPodManagement),
},
},
},
{
name: "1 replica, size 2, exclusive placement enabled",
pod: &corev1.Pod{
ObjectMeta: v1.ObjectMeta{
Name: "test-sample",
Namespace: "default",
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/worker-index": "0",
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
},
lws: testutils.BuildBasicLeaderWorkerSet("test-sample", "default").
Replica(1).
WorkerTemplateSpec(testutils.MakeWorkerPodSpec()).
Annotation(map[string]string{
"leaderworkerset.sigs.k8s.io/exclusive-topology": "cloud.google.com/gke-nodepool",
}).Size(2).Obj(),
wantStatefulSetConfig: &appsapplyv1.StatefulSetApplyConfiguration{
TypeMetaApplyConfiguration: metaapplyv1.TypeMetaApplyConfiguration{
Kind: ptr.To[string]("StatefulSet"),
APIVersion: ptr.To[string]("apps/v1"),
},
ObjectMetaApplyConfiguration: &metaapplyv1.ObjectMetaApplyConfiguration{
Name: ptr.To[string]("test-sample"),
Namespace: ptr.To[string]("default"),
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
Spec: &appsapplyv1.StatefulSetSpecApplyConfiguration{
Replicas: ptr.To[int32](1),
Selector: &metaapplyv1.LabelSelectorApplyConfiguration{
MatchLabels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
},
Template: &coreapplyv1.PodTemplateSpecApplyConfiguration{
ObjectMetaApplyConfiguration: &metaapplyv1.ObjectMetaApplyConfiguration{
Labels: map[string]string{
"leaderworkerset.sigs.k8s.io/name": "test-sample",
"leaderworkerset.sigs.k8s.io/group-index": "1",
"leaderworkerset.sigs.k8s.io/group-key": "test-key",
},
Annotations: map[string]string{
"leaderworkerset.sigs.k8s.io/size": "2",
"leaderworkerset.sigs.k8s.io/leader-name": "test-sample",
"leaderworkerset.sigs.k8s.io/exclusive-topology": "cloud.google.com/gke-nodepool",
},
},
Spec: &coreapplyv1.PodSpecApplyConfiguration{
Containers: []coreapplyv1.ContainerApplyConfiguration{
{
Name: ptr.To[string]("leader"),
Image: ptr.To[string]("nginx:1.14.2"),
Ports: []coreapplyv1.ContainerPortApplyConfiguration{{ContainerPort: ptr.To[int32](8080), Protocol: ptr.To[corev1.Protocol](corev1.ProtocolTCP)}},
Resources: &coreapplyv1.ResourceRequirementsApplyConfiguration{},
},
},
},
},
Ordinals: &appsapplyv1.StatefulSetOrdinalsApplyConfiguration{Start: ptr.To[int32](1)},
ServiceName: ptr.To[string]("test-sample"),
PodManagementPolicy: ptr.To[appsv1.PodManagementPolicyType](appsv1.ParallelPodManagement),
},
},
},
}

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
statefulSetConfig, err := constructWorkerStatefulSetApplyConfiguration(*tc.pod, *tc.lws)
if err != nil {
t.Errorf("failed with error %s", err.Error())
}
if diff := cmp.Diff(tc.wantStatefulSetConfig, statefulSetConfig); diff != "" {
t.Errorf("unexpected StatefulSet apply operation %s", diff)
}

})
}
}

func TestExclusiveConditionTypes(t *testing.T) {
tests := []struct {
name string
Expand Down
Loading

0 comments on commit 0e5b557

Please sign in to comment.