Skip to content
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
24 changes: 19 additions & 5 deletions internal/cmd/compute/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,8 @@ template, so setting or removing one replaces the workload's instances.

All of these carry forward. A deploy that does not mention a variable, an
import, a mount, or a label keeps the one the workload already has, so a
routine image bump changes nothing else. Remove one explicitly with a trailing
routine image bump changes nothing else. Image pull secrets and sysctls set
by a manifest carry forward too. Remove one explicitly with a trailing
"-": --env KEY-, --env-from-secret NAME-, --configmap NAME-, --label key-.`,
Args: cobra.MaximumNArgs(1),
Example: ` # Deploy with flags
Expand Down Expand Up @@ -599,10 +600,8 @@ func deployFromFlags(cmd *cobra.Command, workloadName string, opts *options) err
Resources: computev1alpha.InstanceRuntimeResources{
InstanceType: inputs.instanceType,
},
Sandbox: &computev1alpha.SandboxRuntime{
Containers: []computev1alpha.SandboxContainer{container},
},
Class: runtimeClass,
Sandbox: sandboxRuntime(&workload, creating, container),
Class: runtimeClass,
},
NetworkInterfaces: networkInterfaces,
Volumes: config.volumes,
Expand Down Expand Up @@ -1043,6 +1042,21 @@ func resolveRuntimeClass(existing *computev1alpha.Workload, creating bool, reque
existing.Name, current, requested, existing.Name)
}

// sandboxRuntime returns the sandbox a flag-driven deploy writes: the one
// container the flags describe, plus the existing workload's image pull
// secrets and sysctls. No flag sets those, so rewriting the sandbox without
// them would silently drop them and leave a private image unpullable.
func sandboxRuntime(existing *computev1alpha.Workload, creating bool, container computev1alpha.SandboxContainer) *computev1alpha.SandboxRuntime {
sandbox := &computev1alpha.SandboxRuntime{
Containers: []computev1alpha.SandboxContainer{container},
}
if current := existing.Spec.Template.Spec.Runtime.Sandbox; !creating && current != nil {
sandbox.ImagePullSecrets = current.ImagePullSecrets
sandbox.Sysctls = current.Sysctls
}
return sandbox
}

// resolveNetworkInterfaces returns the network interfaces a flag-driven deploy
// writes. A new workload gets one interface on the requested network, or on
// "default" when none is requested.
Expand Down
46 changes: 46 additions & 0 deletions internal/cmd/compute/deploy/sandbox_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: AGPL-3.0-only

package deploy

import (
"reflect"
"testing"

computev1alpha "go.datum.net/compute/api/v1alpha"
)

func TestSandboxRuntime(t *testing.T) {
secrets := []computev1alpha.LocalSecretReference{{Name: "registry-creds"}}
sysctls := []computev1alpha.SandboxSysctl{{Name: "net.core.somaxconn", Value: "1024"}}
container := computev1alpha.SandboxContainer{Name: containerName, Image: "ghcr.io/acme/api:2"}

stored := workloadWithPorts()
stored.Spec.Template.Spec.Runtime.Sandbox.ImagePullSecrets = secrets
stored.Spec.Template.Spec.Runtime.Sandbox.Sysctls = sysctls

tests := []struct {
name string
existing *computev1alpha.Workload
creating bool
wantSecrets []computev1alpha.LocalSecretReference
wantSysctls []computev1alpha.SandboxSysctl
}{
{name: "redeploy keeps pull secrets and sysctls", existing: &stored, wantSecrets: secrets, wantSysctls: sysctls},
{name: "create starts empty", existing: workload(), creating: true},
{name: "redeploy of a workload without a sandbox", existing: workload()},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := sandboxRuntime(tt.existing, tt.creating, container)
if !reflect.DeepEqual(got.Containers, []computev1alpha.SandboxContainer{container}) {
t.Errorf("containers = %+v, want only the flag-built container", got.Containers)
}
if !reflect.DeepEqual(got.ImagePullSecrets, tt.wantSecrets) {
t.Errorf("imagePullSecrets = %+v, want %+v", got.ImagePullSecrets, tt.wantSecrets)
}
if !reflect.DeepEqual(got.Sysctls, tt.wantSysctls) {
t.Errorf("sysctls = %+v, want %+v", got.Sysctls, tt.wantSysctls)
}
})
}
}
Loading