Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ mocks: mockery mocks-clean ## 🪄 Generate mocks

.PHONY: manifests
manifests: controller-gen ## 🪄 Clean mocks
$(CONTROLLER_GEN) rbac:roleName=rig crd webhook paths="./pkg/api/..." output:dir=deploy/kustomize output:crd:dir=deploy/kustomize/crd/bases
$(CONTROLLER_GEN) rbac:roleName=rig crd webhook \
paths="./pkg/api/..." \
output:dir=deploy/kustomize \
output:webhook:dir=deploy/kustomize/webhook \
output:crd:dir=deploy/kustomize/crd/bases

.PHONY: generate-k8s
generate-k8s: controller-gen ## 🪄 Generate runtime.Object implementations.
Expand All @@ -86,15 +90,17 @@ test-all: gotestsum setup-envtest ## ✅ Run all tests
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(TOOLSBIN) -p path)" \
$(GOTESTSUM) \
--format-hide-empty-pkg \
--junitfile test-result.xml
--junitfile test-result.xml && \
killall etcd || true

.PHONY: test-integration
test-integration: gotestsum setup-envtest ## ✅ Run integration tests
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(TOOLSBIN) -p path)" \
KUBEBUILDER_ASSETS="$(shell $(SETUP_ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(TOOLSBIN) -p path)" && \
$(GOTESTSUM) \
--format-hide-empty-pkg \
--junitfile test-result.xml -- \
-run "^TestIntegration" ./...
-run "^TestIntegration" ./... && \
killall etcd || true

.PHONY: run
run: build-rig-server ## 🏃 Run rig-server
Expand Down
8 changes: 6 additions & 2 deletions internal/client/docker/capsule_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/rigdev/rig/pkg/api/v1alpha1"
"github.com/rigdev/rig/pkg/errors"
"github.com/rigdev/rig/pkg/iterator"
"github.com/rigdev/rig/pkg/ptr"
"go.uber.org/zap"
"golang.org/x/exp/slices"
v1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -109,7 +110,7 @@ func (c *Client) applyCapsuleConfig(ctx context.Context, capsuleID string) error

var cmd []string
if cfg.Spec.Command != "" {
cmd = append([]string{cfg.Spec.Image}, cfg.Spec.Args...)
cmd = append([]string{image}, cfg.Spec.Args...)
}

dcc := &container.Config{
Expand Down Expand Up @@ -172,7 +173,10 @@ func (c *Client) applyCapsuleConfig(ctx context.Context, capsuleID string) error
}
}

for i := 0; i < int(cfg.Spec.Replicas); i++ {
if cfg.Spec.Replicas == nil {
cfg.Spec.Replicas = ptr.New(int32(1))
}
for i := 0; i < int(*cfg.Spec.Replicas); i++ {
containerID := fmt.Sprint(cfg.GetName(), "-instance-", i)

dnc.EndpointsConfig[netID] = &network.EndpointSettings{
Expand Down
7 changes: 6 additions & 1 deletion internal/client/k8s/capsule_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,19 @@ func (c *Client) applyCapsuleConfig(ctx context.Context, capsuleID string) error
}
}

replicas := int32(1)
if cfg.Spec.Replicas != nil {
replicas = *cfg.Spec.Replicas
}

return c.upsertCapsule(ctx, cfg.GetName(), &cluster.Capsule{
CapsuleID: cfg.GetName(),
Image: cfg.Spec.Image,
ContainerSettings: &capsule.ContainerSettings{
EnvironmentVariables: envs,
},
Network: network,
Replicas: uint32(cfg.Spec.Replicas),
Replicas: uint32(replicas),
Namespace: cfg.GetNamespace(),
RegistryAuth: regAuth,
ConfigFiles: cf,
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/capsule_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ func createDeployment(
labelRigDevCapsule: capsule.Name,
},
},
Replicas: &capsule.Spec.Replicas,
Replicas: capsule.Spec.Replicas,
Template: v1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
Expand Down
3 changes: 2 additions & 1 deletion internal/service/capsule/rollout.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/rigdev/rig/pkg/api/v1alpha1"
"github.com/rigdev/rig/pkg/auth"
"github.com/rigdev/rig/pkg/errors"
"github.com/rigdev/rig/pkg/ptr"
"github.com/rigdev/rig/pkg/utils"
"github.com/rigdev/rig/pkg/uuid"
"go.uber.org/zap"
Expand Down Expand Up @@ -472,7 +473,7 @@ func (j *rolloutJob) run(
cfg.Spec.Image = rc.GetBuildId()
cfg.Spec.Command = rc.GetContainerSettings().GetCommand()
cfg.Spec.Args = rc.GetContainerSettings().GetArgs()
cfg.Spec.Replicas = int32(rc.GetReplicas())
cfg.Spec.Replicas = ptr.New(int32(rc.GetReplicas()))

addNext:
for _, cf := range rc.GetConfigFiles() {
Expand Down
14 changes: 10 additions & 4 deletions pkg/api/v1alpha1/capsule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import (

// CapsuleSpec defines the desired state of Capsule
type CapsuleSpec struct {
Replicas int32 `json:"replicas"`
Image string `json:"image"`
Replicas *int32 `json:"replicas,omitempty"`
Image string `json:"image"`

Command string `json:"command,omitempty"`
Args []string `json:"args,omitempty"`
Interfaces []CapsuleInterface `json:"interfaces,omitempty"`
Expand All @@ -19,8 +20,11 @@ type CapsuleSpec struct {

// CapsuleInterface defines an interface for a capsule
type CapsuleInterface struct {
Port int32 `json:"port"`
Name string `json:"name"`
Name string `json:"name"`
//+kubebuilder:validation:Minimum=1
//+kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`

Public *CapsulePublicInterface `json:"public,omitempty"`
}

Expand All @@ -39,6 +43,8 @@ type CapsuleInterfaceIngress struct {
// CapsuleInterfaceLoadBalancer defines that the interface should be exposed as
// a L4 loadbalancer
type CapsuleInterfaceLoadBalancer struct {
//+kubebuilder:validation:Minimum=1
//+kubebuilder:validation:Maximum=65535
Port int32 `json:"port"`
}

Expand Down
47 changes: 47 additions & 0 deletions pkg/api/v1alpha1/capsule_webhook.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package v1alpha1

import (
"github.com/rigdev/rig/pkg/ptr"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -25,6 +26,10 @@ var _ webhook.Defaulter = &Capsule{}
// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Capsule) Default() {
capsulelog.Info("default", "name", r.Name)

if r.Spec.Replicas == nil {
r.Spec.Replicas = ptr.New(int32(1))
}
}

//+kubebuilder:webhook:path=/validate-rig-dev-v1alpha1-capsule,mutating=false,failurePolicy=fail,sideEffects=None,groups=rig.dev,resources=capsules,verbs=create;update,versions=v1alpha1,name=vcapsule.kb.io,admissionReviewVersions=v1
Expand Down Expand Up @@ -56,6 +61,10 @@ func (r *Capsule) validate() (admission.Warnings, error) {
errs field.ErrorList
)

warns, errs = r.validateSpec()
allWarns = append(allWarns, warns...)
allErrs = append(allErrs, errs...)

warns, errs = r.validateInterfaces()
allWarns = append(allWarns, warns...)
allErrs = append(allErrs, errs...)
Expand All @@ -67,6 +76,15 @@ func (r *Capsule) validate() (admission.Warnings, error) {
return allWarns, allErrs.ToAggregate()
}

func (r *Capsule) validateSpec() (admission.Warnings, field.ErrorList) {
var errs field.ErrorList

if r.Spec.Image == "" {
errs = append(errs, field.Required(field.NewPath("spec").Child("image"), ""))
}
return nil, errs
}

func (r *Capsule) validateInterfaces() (admission.Warnings, field.ErrorList) {
if len(r.Spec.Interfaces) == 0 {
return nil, nil
Expand All @@ -80,6 +98,10 @@ func (r *Capsule) validateInterfaces() (admission.Warnings, field.ErrorList) {
for i, inf := range r.Spec.Interfaces {
infPath := infsPath.Index(i)

if inf.Name == "" {
errs = append(errs, field.Required(infPath.Child("name"), ""))
}

if _, ok := names[inf.Name]; ok {
errs = append(errs, field.Duplicate(infPath.Child("name"), inf.Name))
} else {
Expand All @@ -101,6 +123,9 @@ func (r *Capsule) validateInterfaces() (admission.Warnings, field.ErrorList) {
if public.Ingress != nil && public.LoadBalancer != nil {
errs = append(errs, field.Invalid(publicPath, public, "ingress and loadBalancer are mutually exclusive"))
}
if public.Ingress != nil && public.Ingress.Host == "" {
errs = append(errs, field.Required(publicPath.Child("ingress").Child("host"), ""))
}
}
}

Expand All @@ -115,6 +140,10 @@ func (r *Capsule) validateFiles() (admission.Warnings, field.ErrorList) {
for i, f := range r.Spec.Files {
fPath := filesPath.Index(i)

if f.Path == "" {
errs = append(errs, field.Required(fPath.Child("path"), ""))
}

if _, ok := paths[f.Path]; ok {
errs = append(errs, field.Duplicate(fPath.Child("path"), f.Path))
} else {
Expand All @@ -127,6 +156,24 @@ func (r *Capsule) validateFiles() (admission.Warnings, field.ErrorList) {
if f.Secret == nil && f.ConfigMap == nil {
errs = append(errs, field.Required(fPath, "one of configMap or secret is required"))
}

if f.Secret != nil {
if f.Secret.Name == "" {
errs = append(errs, field.Required(fPath.Child("secret").Child("name"), ""))
}
if f.Secret.Key == "" {
errs = append(errs, field.Required(fPath.Child("secret").Child("key"), ""))
}
}

if f.ConfigMap != nil {
if f.ConfigMap.Name == "" {
errs = append(errs, field.Required(fPath.Child("configMap").Child("name"), ""))
}
if f.ConfigMap.Key == "" {
errs = append(errs, field.Required(fPath.Child("configMap").Child("key"), ""))
}
}
}

return nil, errs
Expand Down
Loading