diff --git a/api/core/v1beta1/site_types.go b/api/core/v1beta1/site_types.go index 222c13f..1373ffc 100644 --- a/api/core/v1beta1/site_types.go +++ b/api/core/v1beta1/site_types.go @@ -228,6 +228,18 @@ type InternalPackageManagerSpec struct { ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // Command overrides the container's entrypoint command. If unset (along with Args), + // defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + // backwards compatibility with existing deployments. + // +optional + Command []string `json:"command,omitempty"` + + // Args overrides the container's command arguments. If unset (along with Command), + // defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + // backwards compatibility with existing deployments. + // +optional + Args []string `json:"args,omitempty"` + S3Bucket string `json:"s3Bucket,omitempty"` Replicas int `json:"replicas,omitempty"` @@ -307,6 +319,18 @@ type InternalConnectSpec struct { ImagePullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // Command overrides the container's entrypoint command. If unset (along with Args), + // defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + // backwards compatibility with existing deployments. + // +optional + Command []string `json:"command,omitempty"` + + // Args overrides the container's command arguments. If unset (along with Command), + // defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + // backwards compatibility with existing deployments. + // +optional + Args []string `json:"args,omitempty"` + Databricks *DatabricksConfig `json:"databricks,omitempty"` LoggedInWarning string `json:"loggedInWarning,omitempty"` diff --git a/api/core/v1beta1/zz_generated.deepcopy.go b/api/core/v1beta1/zz_generated.deepcopy.go index 231faf4..633b0c4 100644 --- a/api/core/v1beta1/zz_generated.deepcopy.go +++ b/api/core/v1beta1/zz_generated.deepcopy.go @@ -1272,6 +1272,16 @@ func (in *InternalConnectSpec) DeepCopyInto(out *InternalConnectSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.Databricks != nil { in, out := &in.Databricks, &out.Databricks *out = new(DatabricksConfig) @@ -1397,6 +1407,16 @@ func (in *InternalPackageManagerSpec) DeepCopyInto(out *InternalPackageManagerSp (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Command != nil { + in, out := &in.Command, &out.Command + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Args != nil { + in, out := &in.Args, &out.Args + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.GitSSHKeys != nil { in, out := &in.GitSSHKeys, &out.GitSSHKeys *out = make([]SSHKeyConfig, len(*in)) diff --git a/client-go/applyconfiguration/core/v1beta1/internalconnectspec.go b/client-go/applyconfiguration/core/v1beta1/internalconnectspec.go index a24302e..3ccb4a0 100644 --- a/client-go/applyconfiguration/core/v1beta1/internalconnectspec.go +++ b/client-go/applyconfiguration/core/v1beta1/internalconnectspec.go @@ -26,6 +26,8 @@ type InternalConnectSpecApplyConfiguration struct { Image *string `json:"image,omitempty"` SessionImage *string `json:"sessionImage,omitempty"` ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"` + Command []string `json:"command,omitempty"` + Args []string `json:"args,omitempty"` Databricks *DatabricksConfigApplyConfiguration `json:"databricks,omitempty"` LoggedInWarning *string `json:"loggedInWarning,omitempty"` PublicWarning *string `json:"publicWarning,omitempty"` @@ -164,6 +166,26 @@ func (b *InternalConnectSpecApplyConfiguration) WithImagePullPolicy(value v1.Pul return b } +// WithCommand adds the given value to the Command field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Command field. +func (b *InternalConnectSpecApplyConfiguration) WithCommand(values ...string) *InternalConnectSpecApplyConfiguration { + for i := range values { + b.Command = append(b.Command, values[i]) + } + return b +} + +// WithArgs adds the given value to the Args field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Args field. +func (b *InternalConnectSpecApplyConfiguration) WithArgs(values ...string) *InternalConnectSpecApplyConfiguration { + for i := range values { + b.Args = append(b.Args, values[i]) + } + return b +} + // WithDatabricks sets the Databricks field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the Databricks field is set to the value of the last call. diff --git a/client-go/applyconfiguration/core/v1beta1/internalpackagemanagerspec.go b/client-go/applyconfiguration/core/v1beta1/internalpackagemanagerspec.go index 4d72141..3977107 100644 --- a/client-go/applyconfiguration/core/v1beta1/internalpackagemanagerspec.go +++ b/client-go/applyconfiguration/core/v1beta1/internalpackagemanagerspec.go @@ -23,6 +23,8 @@ type InternalPackageManagerSpecApplyConfiguration struct { EnvVars []v1.EnvVar `json:"envVars,omitempty"` Image *string `json:"image,omitempty"` ImagePullPolicy *v1.PullPolicy `json:"imagePullPolicy,omitempty"` + Command []string `json:"command,omitempty"` + Args []string `json:"args,omitempty"` S3Bucket *string `json:"s3Bucket,omitempty"` Replicas *int `json:"replicas,omitempty"` DomainPrefix *string `json:"domainPrefix,omitempty"` @@ -134,6 +136,26 @@ func (b *InternalPackageManagerSpecApplyConfiguration) WithImagePullPolicy(value return b } +// WithCommand adds the given value to the Command field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Command field. +func (b *InternalPackageManagerSpecApplyConfiguration) WithCommand(values ...string) *InternalPackageManagerSpecApplyConfiguration { + for i := range values { + b.Command = append(b.Command, values[i]) + } + return b +} + +// WithArgs adds the given value to the Args field in the declarative configuration +// and returns the receiver, so that objects can be build by chaining "With" function invocations. +// If called multiple times, values provided by each call will be appended to the Args field. +func (b *InternalPackageManagerSpecApplyConfiguration) WithArgs(values ...string) *InternalPackageManagerSpecApplyConfiguration { + for i := range values { + b.Args = append(b.Args, values[i]) + } + return b +} + // WithS3Bucket sets the S3Bucket field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the S3Bucket field is set to the value of the last call. diff --git a/config/crd/bases/core.posit.team_sites.yaml b/config/crd/bases/core.posit.team_sites.yaml index 8acbbf4..5296908 100644 --- a/config/crd/bases/core.posit.team_sites.yaml +++ b/config/crd/bases/core.posit.team_sites.yaml @@ -203,6 +203,14 @@ spec: - rVersion type: object type: array + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: properties: administratorRoleMapping: @@ -259,6 +267,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array databaseSettings: properties: instrumentationSchema: @@ -941,6 +957,14 @@ spec: description: AdditionalConfig allows appending arbitrary gcfg config content to the generated config. type: string + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: description: Auth configures OIDC authentication for Package Manager's web UI @@ -1012,6 +1036,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array domainPrefix: default: packagemanager type: string diff --git a/dist/chart/templates/crd/core.posit.team_sites.yaml b/dist/chart/templates/crd/core.posit.team_sites.yaml index 5455a14..14d65f7 100755 --- a/dist/chart/templates/crd/core.posit.team_sites.yaml +++ b/dist/chart/templates/crd/core.posit.team_sites.yaml @@ -224,6 +224,14 @@ spec: - rVersion type: object type: array + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: properties: administratorRoleMapping: @@ -280,6 +288,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array databaseSettings: properties: instrumentationSchema: @@ -962,6 +978,14 @@ spec: description: AdditionalConfig allows appending arbitrary gcfg config content to the generated config. type: string + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: description: Auth configures OIDC authentication for Package Manager's web UI @@ -1033,6 +1057,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array domainPrefix: default: packagemanager type: string diff --git a/internal/controller/core/site_controller_connect.go b/internal/controller/core/site_controller_connect.go index 22786c7..1b9450d 100644 --- a/internal/controller/core/site_controller_connect.go +++ b/internal/controller/core/site_controller_connect.go @@ -140,6 +140,8 @@ func (r *SiteReconciler) reconcileConnect( Image: site.Spec.Connect.Image, SessionImage: site.Spec.Connect.SessionImage, ImagePullPolicy: site.Spec.Connect.ImagePullPolicy, + Command: site.Spec.Connect.Command, + Args: site.Spec.Connect.Args, ImagePullSecrets: site.Spec.ImagePullSecrets, ChronicleAgentImage: site.Spec.Chronicle.AgentImage, AdditionalVolumes: additionalVolumes, diff --git a/internal/controller/core/site_controller_package_manager.go b/internal/controller/core/site_controller_package_manager.go index 3b7a049..8db5247 100644 --- a/internal/controller/core/site_controller_package_manager.go +++ b/internal/controller/core/site_controller_package_manager.go @@ -95,6 +95,8 @@ func (r *SiteReconciler) reconcilePackageManager( IngressAnnotations: site.Spec.IngressAnnotations, Image: site.Spec.PackageManager.Image, ImagePullPolicy: site.Spec.PackageManager.ImagePullPolicy, + Command: site.Spec.PackageManager.Command, + Args: site.Spec.PackageManager.Args, ImagePullSecrets: site.Spec.ImagePullSecrets, ChronicleAgentImage: site.Spec.Chronicle.AgentImage, NodeSelector: site.Spec.PackageManager.NodeSelector, diff --git a/internal/controller/core/site_test.go b/internal/controller/core/site_test.go index 85fbf3e..d55f0b4 100644 --- a/internal/controller/core/site_test.go +++ b/internal/controller/core/site_test.go @@ -1256,6 +1256,62 @@ func TestSiteReconciler_RegisterOnFirstLoginDefaultNil(t *testing.T) { assert.Nil(t, testConnect.Spec.RegisterOnFirstLogin) } +func TestSiteReconciler_ConnectCommandArgsPropagation(t *testing.T) { + siteName := "connect-command-args" + siteNamespace := "posit-team" + site := defaultSite(siteName) + site.Spec.Connect.Command = []string{"/usr/local/bin/startup.sh"} + site.Spec.Connect.Args = []string{"--foo"} + + cli, _, err := runFakeSiteReconciler(t, siteNamespace, siteName, site) + assert.Nil(t, err) + + testConnect := getConnect(t, cli, siteNamespace, siteName) + assert.Equal(t, []string{"/usr/local/bin/startup.sh"}, testConnect.Spec.Command) + assert.Equal(t, []string{"--foo"}, testConnect.Spec.Args) +} + +func TestSiteReconciler_ConnectCommandArgsDefaultNil(t *testing.T) { + siteName := "connect-command-args-default" + siteNamespace := "posit-team" + site := defaultSite(siteName) + + cli, _, err := runFakeSiteReconciler(t, siteNamespace, siteName, site) + assert.Nil(t, err) + + testConnect := getConnect(t, cli, siteNamespace, siteName) + assert.Nil(t, testConnect.Spec.Command) + assert.Nil(t, testConnect.Spec.Args) +} + +func TestSiteReconciler_PackageManagerCommandArgsPropagation(t *testing.T) { + siteName := "packagemanager-command-args" + siteNamespace := "posit-team" + site := defaultSite(siteName) + site.Spec.PackageManager.Command = []string{"/usr/local/bin/startup.sh"} + site.Spec.PackageManager.Args = []string{"--foo"} + + cli, _, err := runFakeSiteReconciler(t, siteNamespace, siteName, site) + assert.Nil(t, err) + + testPackageManager := getPackageManager(t, cli, siteNamespace, siteName) + assert.Equal(t, []string{"/usr/local/bin/startup.sh"}, testPackageManager.Spec.Command) + assert.Equal(t, []string{"--foo"}, testPackageManager.Spec.Args) +} + +func TestSiteReconciler_PackageManagerCommandArgsDefaultNil(t *testing.T) { + siteName := "packagemanager-command-args-default" + siteNamespace := "posit-team" + site := defaultSite(siteName) + + cli, _, err := runFakeSiteReconciler(t, siteNamespace, siteName, site) + assert.Nil(t, err) + + testPackageManager := getPackageManager(t, cli, siteNamespace, siteName) + assert.Nil(t, testPackageManager.Spec.Command) + assert.Nil(t, testPackageManager.Spec.Args) +} + func TestSiteReconciler_BaseDomainNotSet(t *testing.T) { siteName := "base-domain-not-set" siteNamespace := "posit-team" diff --git a/internal/crdapply/bases/core.posit.team_sites.yaml b/internal/crdapply/bases/core.posit.team_sites.yaml index 8acbbf4..5296908 100644 --- a/internal/crdapply/bases/core.posit.team_sites.yaml +++ b/internal/crdapply/bases/core.posit.team_sites.yaml @@ -203,6 +203,14 @@ spec: - rVersion type: object type: array + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: properties: administratorRoleMapping: @@ -259,6 +267,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array databaseSettings: properties: instrumentationSchema: @@ -941,6 +957,14 @@ spec: description: AdditionalConfig allows appending arbitrary gcfg config content to the generated config. type: string + args: + description: |- + Args overrides the container's command arguments. If unset (along with Command), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array auth: description: Auth configures OIDC authentication for Package Manager's web UI @@ -1012,6 +1036,14 @@ spec: BaseDomain overrides site.Spec.Domain for this product's URL construction. When set, the product URL will be: domainPrefix.baseDomain type: string + command: + description: |- + Command overrides the container's entrypoint command. If unset (along with Args), + defaults to the historical "tini -- /usr/local/bin/startup.sh" wrapper for + backwards compatibility with existing deployments. + items: + type: string + type: array domainPrefix: default: packagemanager type: string