Skip to content

Commit 9203986

Browse files
authored
feat: Web Based Terminal (argoproj-labs#2171)
* feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> * feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> * feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> * feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> * feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> * feat: Web Based Terminal Signed-off-by: akhil nittala <nakhil@redhat.com> --------- Signed-off-by: akhil nittala <nakhil@redhat.com>
1 parent 3a9dc79 commit 9203986

11 files changed

Lines changed: 76 additions & 5 deletions

File tree

api/v1beta1/argocd_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,8 @@ type ArgoCDSpec struct {
10791079
// WebhookSecrets references Kubernetes Secrets that supply webhook credentials per provider.
10801080
// The operator syncs values into argocd-secret under the keys Argo CD expects.
10811081
WebhookSecrets *ArgoCDWebhookSecretsSpec `json:"webhookSecrets,omitempty"`
1082+
// WebTerminalEnabled allows you to get a shell inside a running pod just like you would with kubectl exec
1083+
WebTerminalEnabled *bool `json:"webTerminalEnabled,omitempty"`
10821084
}
10831085

10841086
// NamespaceManagement defines the namespace management settings

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bundle/manifests/argocd-operator.clusterserviceversion.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ metadata:
257257
capabilities: Deep Insights
258258
categories: Integration & Delivery
259259
certified: "false"
260-
createdAt: "2026-04-22T19:10:17Z"
260+
createdAt: "2026-05-04T10:20:49Z"
261261
description: Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
262262
operators.operatorframework.io/builder: operator-sdk-v1.35.0
263263
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4

bundle/manifests/argoproj.io_argocds.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32258,6 +32258,10 @@ spec:
3225832258
description: Version is the tag to use with the ArgoCD container image
3225932259
for all ArgoCD components.
3226032260
type: string
32261+
webTerminalEnabled:
32262+
description: WebTerminalEnabled allows you to get a shell inside a
32263+
running pod just like you would with kubectl exec
32264+
type: boolean
3226132265
webhookSecrets:
3226232266
description: |-
3226332267
WebhookSecrets references Kubernetes Secrets that supply webhook credentials per provider.

common/defaults.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,8 @@ vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOf
309309

310310
// ArgoCDDefaultClusterDomain is the default cluster domain suffix for service FQDNs.
311311
ArgoCDDefaultClusterDomain = "cluster.local"
312+
// ArgoCDDefaultWebTerminalEnabled is the default web terminal enabled switch.
313+
ArgoCDDefaultWebTerminalEnabled = "false"
312314
)
313315

314316
// DefaultLabels returns the default set of labels for controllers.

common/keys.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,8 @@ const (
258258
// ArgoCDImagePullPolicyEnvName is the environment variable used to get the global image pull policy
259259
// for all ArgoCD components managed by the operator.
260260
ArgoCDImagePullPolicyEnvName = "IMAGE_PULL_POLICY"
261+
// ArgoCDWebTerminalEnabledKey is the configuration key for enabling the web terminal.
262+
ArgoCDWebTerminalEnabledKey = "exec.enabled"
263+
// ArgoCDWebTerminalEnabledDefaultValue is the default value for enabling the web terminal.
264+
ArgoCDWebTerminalEnabledDefaultValue = false
261265
)

config/crd/bases/argoproj.io_argocds.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32247,6 +32247,10 @@ spec:
3224732247
description: Version is the tag to use with the ArgoCD container image
3224832248
for all ArgoCD components.
3224932249
type: string
32250+
webTerminalEnabled:
32251+
description: WebTerminalEnabled allows you to get a shell inside a
32252+
running pod just like you would with kubectl exec
32253+
type: boolean
3225032254
webhookSecrets:
3225132255
description: |-
3225232256
WebhookSecrets references Kubernetes Secrets that supply webhook credentials per provider.

controllers/argocd/configmap.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ import (
1818
"context"
1919
"fmt"
2020
"reflect"
21+
"strconv"
2122
"strings"
2223

2324
"gopkg.in/yaml.v2"
25+
appsv1 "k8s.io/api/apps/v1"
2426
corev1 "k8s.io/api/core/v1"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2628
"k8s.io/apimachinery/pkg/runtime"
@@ -386,6 +388,7 @@ func (r *ReconcileArgoCD) reconcileArgoConfigMap(cr *argoproj.ArgoCD) error {
386388
cm.Data[common.ArgoCDKeyHelpChatURL] = getHelpChatURL(cr)
387389
cm.Data[common.ArgoCDKeyHelpChatText] = getHelpChatText(cr)
388390
cm.Data[common.ArgoCDKeyKustomizeBuildOptions] = getKustomizeBuildOptions(cr)
391+
cm.Data[common.ArgoCDWebTerminalEnabledKey] = strconv.FormatBool(isWebTerminalEnabled(cr))
389392

390393
// Set installationID as a top-level key
391394
if cr.Spec.InstallationID != "" {
@@ -522,7 +525,10 @@ func (r *ReconcileArgoCD) reconcileArgoConfigMap(cr *argoproj.ArgoCD) error {
522525
return err
523526
}
524527
if found {
525-
528+
webTerminalFlagChanged := false
529+
if cm.Data[common.ArgoCDWebTerminalEnabledKey] != existingCM.Data[common.ArgoCDWebTerminalEnabledKey] {
530+
webTerminalFlagChanged = true
531+
}
526532
// reconcile dex configuration if dex is enabled `.spec.sso.dex.provider` or there is
527533
// existing dex configuration
528534
if UseDex(cr) {
@@ -558,7 +564,23 @@ func (r *ReconcileArgoCD) reconcileArgoConfigMap(cr *argoproj.ArgoCD) error {
558564
explanation += ", owner reference"
559565
}
560566
argoutil.LogResourceUpdate(log, existingCM, explanation)
561-
return r.Update(context.TODO(), existingCM)
567+
err = r.Update(context.TODO(), existingCM)
568+
if err != nil {
569+
return err
570+
}
571+
// trigger rollout ONLY if web terminal setting changed
572+
if webTerminalFlagChanged {
573+
log.Info("Web terminal enabled setting changed, triggering ArgoCD server rollout")
574+
apiDepl := &appsv1.Deployment{
575+
ObjectMeta: metav1.ObjectMeta{
576+
Name: nameWithSuffix("server", cr),
577+
Namespace: cr.Namespace,
578+
},
579+
}
580+
if err := r.triggerRollout(apiDepl, "webTerminalEnabled.changed"); err != nil {
581+
return err
582+
}
583+
}
562584
}
563585
return nil // Do nothing as there is no change in the configmap.
564586
}
@@ -1026,3 +1048,11 @@ func getDefaultResourceExclusions() []filteredResource {
10261048
"ClusterBackgroundScanReport", "UpdateRequest"}},
10271049
}
10281050
}
1051+
1052+
// isWebTerminalEnabled will return whether the web terminal is enabled for the given ArgoCD.
1053+
func isWebTerminalEnabled(cr *argoproj.ArgoCD) bool {
1054+
if cr.Spec.WebTerminalEnabled == nil {
1055+
return common.ArgoCDWebTerminalEnabledDefaultValue
1056+
}
1057+
return *cr.Spec.WebTerminalEnabled
1058+
}

controllers/argocd/configmap_test.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import (
3636
logf "sigs.k8s.io/controller-runtime/pkg/log"
3737
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3838

39+
appsv1 "k8s.io/api/apps/v1"
40+
3941
argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
4042
"github.com/argoproj-labs/argocd-operator/common"
4143
"github.com/argoproj-labs/argocd-operator/controllers/argoutil"
@@ -257,6 +259,7 @@ func TestReconcileArgoCD_reconcileArgoConfigMap(t *testing.T) {
257259
"statusbadge.enabled": "false",
258260
"url": "https://argocd-server",
259261
"users.anonymous.enabled": "false",
262+
"exec.enabled": "false",
260263
}
261264

262265
cmdTests := []struct {
@@ -269,6 +272,16 @@ func TestReconcileArgoCD_reconcileArgoConfigMap(t *testing.T) {
269272
[]argoCDOpt{},
270273
map[string]string{},
271274
},
275+
{
276+
"with-web-terminal-enabled",
277+
[]argoCDOpt{func(a *argoproj.ArgoCD) {
278+
val := true
279+
a.Spec.WebTerminalEnabled = &val
280+
}},
281+
map[string]string{
282+
"exec.enabled": "true",
283+
},
284+
},
272285
{
273286
"with-banner",
274287
[]argoCDOpt{func(a *argoproj.ArgoCD) {
@@ -1754,7 +1767,8 @@ p, role:custom-app-viewer, logs, get, */*, allow`
17541767

17551768
func TestReconcileArgoCD_RemovesLegacyLogEnforceFlag(t *testing.T) {
17561769
// Setup fake ArgoCD instance and client
1757-
cr := makeTestArgoCD() // helper to create ArgoCD CR
1770+
cr := makeTestArgoCD()
1771+
17581772
cm := &corev1.ConfigMap{
17591773
ObjectMeta: metav1.ObjectMeta{
17601774
Name: common.ArgoCDConfigMapName,
@@ -1766,7 +1780,9 @@ func TestReconcileArgoCD_RemovesLegacyLogEnforceFlag(t *testing.T) {
17661780
}
17671781

17681782
scheme := runtime.NewScheme()
1783+
17691784
_ = corev1.AddToScheme(scheme)
1785+
_ = appsv1.AddToScheme(scheme)
17701786
_ = argoproj.AddToScheme(scheme)
17711787

17721788
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(cr, cm).Build()

deploy/olm-catalog/argocd-operator/0.19.0/argocd-operator.v0.19.0.clusterserviceversion.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ metadata:
257257
capabilities: Deep Insights
258258
categories: Integration & Delivery
259259
certified: "false"
260-
createdAt: "2026-04-22T19:10:17Z"
260+
createdAt: "2026-05-04T10:20:49Z"
261261
description: Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes.
262262
operators.operatorframework.io/builder: operator-sdk-v1.35.0
263263
operators.operatorframework.io/project_layout: go.kubebuilder.io/v4

0 commit comments

Comments
 (0)