Skip to content

Commit

Permalink
feat: support reference model for workloads (argoproj#676)
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Matyushentsev <[email protected]>
  • Loading branch information
alexmt committed Apr 8, 2021
1 parent e803db0 commit a65a89b
Show file tree
Hide file tree
Showing 13 changed files with 519 additions and 128 deletions.
6 changes: 6 additions & 0 deletions cmd/rollouts-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strconv"
"time"

"k8s.io/client-go/discovery"

smiclientset "github.com/servicemeshinterface/smi-sdk-go/pkg/gen/client/split/clientset/versioned"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
Expand All @@ -26,6 +28,7 @@ import (
jobprovider "github.com/argoproj/argo-rollouts/metricproviders/job"
clientset "github.com/argoproj/argo-rollouts/pkg/client/clientset/versioned"
"github.com/argoproj/argo-rollouts/pkg/signals"
"github.com/argoproj/argo-rollouts/rollout"
"github.com/argoproj/argo-rollouts/rollout/trafficrouting/alb"
"github.com/argoproj/argo-rollouts/rollout/trafficrouting/smi"
controllerutil "github.com/argoproj/argo-rollouts/utils/controller"
Expand Down Expand Up @@ -97,6 +100,8 @@ func newCommand() *cobra.Command {
checkError(err)
dynamicClient, err := dynamic.NewForConfig(config)
checkError(err)
discoveryClient, err := discovery.NewDiscoveryClientForConfig(config)
checkError(err)
smiClient, err := smiclientset.NewForConfig(config)
resyncDuration := time.Duration(rolloutResyncPeriod) * time.Second
kubeInformerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(
Expand Down Expand Up @@ -130,6 +135,7 @@ func newCommand() *cobra.Command {
rolloutClient,
dynamicClient,
smiClient,
rollout.NewInformerBasedWorkloadRefResolver(namespace, dynamicClient, discoveryClient),
kubeInformerFactory.Apps().V1().ReplicaSets(),
kubeInformerFactory.Core().V1().Services(),
kubeInformerFactory.Extensions().V1beta1().Ingresses(),
Expand Down
2 changes: 2 additions & 0 deletions controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ func NewManager(
argoprojclientset clientset.Interface,
dynamicclientset dynamic.Interface,
smiclientset smiclientset.Interface,
refResolver rollout.WorkloadRefResolver,
replicaSetInformer appsinformers.ReplicaSetInformer,
servicesInformer coreinformers.ServiceInformer,
ingressesInformer extensionsinformers.IngressInformer,
Expand Down Expand Up @@ -146,6 +147,7 @@ func NewManager(
KubeClientSet: kubeclientset,
ArgoProjClientset: argoprojclientset,
DynamicClientSet: dynamicclientset,
RefResolver: refResolver,
SmiClientSet: smiclientset,
ExperimentInformer: experimentsInformer,
AnalysisRunInformer: analysisRunInformer,
Expand Down
42 changes: 42 additions & 0 deletions examples/rollout-workload-ref.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/instance: rollout-canary
name: rollout-ref-deployment
spec:
replicas: 0
selector:
matchLabels:
app: rollout-ref-deployment
template:
metadata:
labels:
app: rollout-ref-deployment
spec:
containers:
- name: rollouts-demo
image: argoproj/rollouts-demo:blue
imagePullPolicy: Always
ports:
- containerPort: 8080
---
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
name: rollout-ref-deployment
spec:
replicas: 5
revisionHistoryLimit: 2
selector:
matchLabels:
app: rollout-ref-deployment
workloadRef:
apiVersion: apps/v1
kind: Deployment
name: rollout-ref-deployment
strategy:
canary:
steps:
- setWeight: 20
- pause: {duration: 10s}
122 changes: 0 additions & 122 deletions go.sum

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion manifests/crds/rollout-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3110,9 +3110,17 @@ spec:
- containers
type: object
type: object
workloadRef:
properties:
apiVersion:
type: string
kind:
type: string
name:
type: string
type: object
required:
- selector
- template
type: object
status:
properties:
Expand Down
45 changes: 43 additions & 2 deletions pkg/apis/rollouts/v1alpha1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 45 additions & 1 deletion pkg/apis/rollouts/v1alpha1/types.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package v1alpha1

import (
"encoding/json"
"strconv"
"time"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
Expand All @@ -30,6 +34,7 @@ type Rollout struct {

// RolloutSpec is the spec for a Rollout resource
type RolloutSpec struct {
TemplateResolvedFromRef bool `json:"-"`
// Number of desired pods. This is a pointer to distinguish between explicit
// zero and not specified. Defaults to 1.
// +optional
Expand All @@ -38,8 +43,12 @@ type RolloutSpec struct {
// selected by this will be the ones affected by this rollout.
// It must match the pod template's labels.
Selector *metav1.LabelSelector `json:"selector"`
// WorkloadRef holds a references to a workload that provides Pod template
// +optional
WorkloadRef *RolloutWorkloadRef `json:"workloadRef,omitempty"`
// Template describes the pods that will be created.
Template corev1.PodTemplateSpec `json:"template"`
// +optional
Template corev1.PodTemplateSpec `json:"template,omitempty"`
// Minimum number of seconds for which a newly created pod should be ready
// without any of its container crashing, for it to be considered available.
// Defaults to 0 (pod will be considered available as soon as it is ready)
Expand All @@ -63,6 +72,41 @@ type RolloutSpec struct {
RestartAt *metav1.Time `json:"restartAt,omitempty"`
}

func (s *RolloutSpec) SetResolvedTemplate(template corev1.PodTemplateSpec) {
s.TemplateResolvedFromRef = true
s.Template = template
}

func (s *RolloutSpec) MarshalJSON() ([]byte, error) {
type Alias RolloutSpec

if s.TemplateResolvedFromRef {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&struct {
Alias `json:",inline"`
}{
Alias: (Alias)(*s),
})
if err != nil {
return nil, err
}
unstructured.RemoveNestedField(obj, "template")
return json.Marshal(obj)
}
return json.Marshal(&struct{ *Alias }{
Alias: (*Alias)(s),
})
}

// RolloutWorkloadRef holds a references to a workload that provides Pod template
type RolloutWorkloadRef struct {
// Workload reference API Version
APIVersion string `json:"apiVersion,omitempty"`
// Workload reference kind
Kind string `json:"kind,omitempty"`
// Workload reference name
Name string `json:"name,omitempty"`
}

const (
// DefaultRolloutUniqueLabelKey is the default key of the selector that is added
// to existing ReplicaSets (and label key that is added to its pods) to prevent the existing ReplicaSets
Expand Down
21 changes: 21 additions & 0 deletions pkg/apis/rollouts/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions rollout/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ import (
unstructuredutil "github.com/argoproj/argo-rollouts/utils/unstructured"
)

type WorkloadRefResolver interface {
Resolve(r *v1alpha1.Rollout) error
}

// Controller is the controller implementation for Rollout resources
type Controller struct {
reconcilerBase
Expand Down Expand Up @@ -81,6 +85,7 @@ type ControllerConfig struct {
KubeClientSet kubernetes.Interface
ArgoProjClientset clientset.Interface
DynamicClientSet dynamic.Interface
RefResolver WorkloadRefResolver
SmiClientSet smiclientset.Interface
ExperimentInformer informers.ExperimentInformer
AnalysisRunInformer informers.AnalysisRunInformer
Expand Down Expand Up @@ -112,6 +117,8 @@ type reconcilerBase struct {
dynamicclientset dynamic.Interface
smiclientset smiclientset.Interface

refResolver WorkloadRefResolver

replicaSetLister appslisters.ReplicaSetLister
replicaSetSynced cache.InformerSynced
rolloutsInformer cache.SharedIndexInformer
Expand Down Expand Up @@ -174,6 +181,7 @@ func NewController(cfg ControllerConfig) *Controller {
recorder: cfg.Recorder,
resyncPeriod: cfg.ResyncPeriod,
podRestarter: podRestarter,
refResolver: cfg.RefResolver,
}

controller := &Controller{
Expand Down Expand Up @@ -342,6 +350,11 @@ func (c *Controller) syncHandler(key string) error {
// rollout spec and pod template spec, the hash will be consistent. See issue #70
// This also returns a copy of the rollout to prevent mutation of the informer cache.
r := remarshalRollout(rollout)

if err := c.refResolver.Resolve(r); err != nil {
return err
}

logCtx := logutil.WithRollout(r)
logCtx = logutil.WithVersionFields(logCtx, r)
logCtx.Info("Started syncing rollout")
Expand Down Expand Up @@ -694,6 +707,10 @@ func (c *rolloutContext) getReferencedIngresses() (*[]v1beta1.Ingress, error) {
return &ingresses, nil
}

func (c *rolloutContext) inferPodTemplate(r *v1alpha1.Rollout) error {
return nil
}

func remarshalRollout(r *v1alpha1.Rollout) *v1alpha1.Rollout {
rolloutBytes, err := json.Marshal(r)
if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions rollout/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ const (
}`
)

type FakeWorkloadRefResolver struct {
}

func (f *FakeWorkloadRefResolver) Resolve(rollout *v1alpha1.Rollout) error {
return nil
}

type FakeEventRecorder struct {
Events chan string
}
Expand Down Expand Up @@ -449,6 +456,7 @@ func (f *fixture) newController(resync resyncFunc) (*Controller, informers.Share
IngressWorkQueue: ingressWorkqueue,
MetricsServer: metricsServer,
Recorder: &FakeEventRecorder{},
RefResolver: &FakeWorkloadRefResolver{},
})

var enqueuedObjectsLock sync.Mutex
Expand Down
Loading

0 comments on commit a65a89b

Please sign in to comment.