diff --git a/pkg/apiclient/argo-kube-client.go b/pkg/apiclient/argo-kube-client.go index cd7c1769fc4c..48ccb2a28e0f 100644 --- a/pkg/apiclient/argo-kube-client.go +++ b/pkg/apiclient/argo-kube-client.go @@ -168,6 +168,8 @@ func (a *argoKubeClient) startStores(ctx context.Context, restConfig *restclient } else { a.cwfTmplStore = clusterworkflowtmplserver.NewClusterWorkflowTemplateClientStore() } + } else { + a.cwfTmplStore = clusterworkflowtmplserver.NewNullClusterWorkflowTemplate() } return nil diff --git a/server/apiserver/argoserver.go b/server/apiserver/argoserver.go index b5146210fda8..3f2d541fa717 100644 --- a/server/apiserver/argoserver.go +++ b/server/apiserver/argoserver.go @@ -238,12 +238,14 @@ func (as *argoServer) Run(ctx context.Context, port int, browserOpenFunc func(st log.Fatal(err) } kubeclientset := kubernetes.NewForConfigOrDie(as.restConfig) - var cwftmplInformer *clusterworkflowtemplate.Informer + var cwftmplInformer clusterworkflowtemplate.ClusterWorkflowTemplateInformer if rbacutil.HasAccessToClusterWorkflowTemplates(ctx, kubeclientset, resourceCacheNamespace) { cwftmplInformer, err = clusterworkflowtemplate.NewInformer(as.restConfig) if err != nil { log.Fatal(err) } + } else { + cwftmplInformer = clusterworkflowtemplate.NewNullClusterWorkflowTemplate() } eventRecorderManager := events.NewEventRecorderManager(as.clients.Kubernetes) artifactRepositories := artifactrepositories.New(as.clients.Kubernetes, as.managedNamespace, &config.ArtifactRepository) diff --git a/server/clusterworkflowtemplate/informer.go b/server/clusterworkflowtemplate/informer.go index 5b649aeb5313..89b884ac462b 100644 --- a/server/clusterworkflowtemplate/informer.go +++ b/server/clusterworkflowtemplate/informer.go @@ -20,6 +20,11 @@ const ( workflowTemplateResyncPeriod = 20 * time.Minute ) +type ClusterWorkflowTemplateInformer interface { + Run(stopCh <-chan struct{}) + Getter(ctx context.Context) templateresolution.ClusterWorkflowTemplateGetter +} + var _ types.ClusterWorkflowTemplateStore = &Informer{} type Informer struct { @@ -54,9 +59,10 @@ func (cwti *Informer) Run(stopCh <-chan struct{}) { } // if namespace contains empty string Lister will use the namespace provided during initialization -func (cwti *Informer) Getter(_ context.Context) templateresolution.ClusterWorkflowTemplateGetter { - if cwti.informer == nil { - log.Fatal("Template informer not started") +func (cwti *Informer) Getter(ctx context.Context) templateresolution.ClusterWorkflowTemplateGetter { + if cwti == nil || cwti.informer == nil { + log.Error("Template informer not started") + return nil } - return cwti.informer.Lister() + return templateresolution.WrapClusterWorkflowTemplateLister(cwti.informer.Lister()) } diff --git a/server/clusterworkflowtemplate/null_client_store.go b/server/clusterworkflowtemplate/null_client_store.go new file mode 100644 index 000000000000..99199efc8988 --- /dev/null +++ b/server/clusterworkflowtemplate/null_client_store.go @@ -0,0 +1,21 @@ +package clusterworkflowtemplate + +import ( + "context" + + "github.com/argoproj/argo-workflows/v3/workflow/templateresolution" +) + +// NullClusterWorkflowTemplateStore is a no-op implementation of ClusterWorkflowTemplateStore +// implements both informer and store interfaces +type NullClusterWorkflowTemplateStore struct{} + +func NewNullClusterWorkflowTemplate() *NullClusterWorkflowTemplateStore { + return &NullClusterWorkflowTemplateStore{} +} + +func (NullClusterWorkflowTemplateStore) Getter(context.Context) templateresolution.ClusterWorkflowTemplateGetter { + return &templateresolution.NullClusterWorkflowTemplateGetter{} +} + +func (NullClusterWorkflowTemplateStore) Run(stopCh <-chan struct{}) {} diff --git a/workflow/templateresolution/context.go b/workflow/templateresolution/context.go index 8921da725816..014214430b24 100644 --- a/workflow/templateresolution/context.go +++ b/workflow/templateresolution/context.go @@ -11,6 +11,7 @@ import ( "github.com/argoproj/argo-workflows/v3/errors" wfv1 "github.com/argoproj/argo-workflows/v3/pkg/apis/workflow/v1alpha1" typed "github.com/argoproj/argo-workflows/v3/pkg/client/clientset/versioned/typed/workflow/v1alpha1" + listers "github.com/argoproj/argo-workflows/v3/pkg/client/listers/workflow/v1alpha1" "github.com/argoproj/argo-workflows/v3/workflow/common" ) @@ -57,6 +58,18 @@ func (n *NullClusterWorkflowTemplateGetter) Get(name string) (*wfv1.ClusterWorkf "forbidden: User cannot get resource 'clusterworkflowtemplates' in API group argoproj.io at the cluster scope", name) } +type clusterWorkflowTemplateListerWrapper struct { + lister listers.ClusterWorkflowTemplateLister +} + +func WrapClusterWorkflowTemplateLister(lister listers.ClusterWorkflowTemplateLister) ClusterWorkflowTemplateGetter { + return &clusterWorkflowTemplateListerWrapper{lister: lister} +} + +func (w *clusterWorkflowTemplateListerWrapper) Get(name string) (*wfv1.ClusterWorkflowTemplate, error) { + return w.lister.Get(name) +} + // Get retrieves the WorkflowTemplate of a given name. func (wrapper *clusterWorkflowTemplateInterfaceWrapper) Get(name string) (*wfv1.ClusterWorkflowTemplate, error) { ctx := context.TODO()