Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: allow a custom labels on any resource to surface in the UI (tree view node tags) #11153

Merged
merged 13 commits into from
Nov 18, 2022
7 changes: 6 additions & 1 deletion controller/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,11 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
return nil, fmt.Errorf("controller is configured to ignore cluster %s", cluster.Server)
}

resourceCustomLabel, err := c.settingsMgr.GetResourceCustomLabel()
alexef marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, fmt.Errorf("error getting custom label: %w", err)
}

clusterCacheOpts := []clustercache.UpdateSettingsFunc{
clustercache.SetListSemaphore(semaphore.NewWeighted(clusterCacheListSemaphoreSize)),
clustercache.SetListPageSize(clusterCacheListPageSize),
Expand All @@ -400,7 +405,7 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
clustercache.SetClusterResources(cluster.ClusterResources),
clustercache.SetPopulateResourceInfoHandler(func(un *unstructured.Unstructured, isRoot bool) (interface{}, bool) {
res := &ResourceInfo{}
populateNodeInfo(un, res)
populateNodeInfo(un, res, resourceCustomLabel)
c.lock.RLock()
cacheSettings := c.cacheSettings
c.lock.RUnlock()
Expand Down
9 changes: 8 additions & 1 deletion controller/cache/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ import (
"github.com/argoproj/argo-cd/v2/util/resource"
)

func populateNodeInfo(un *unstructured.Unstructured, res *ResourceInfo) {
func populateNodeInfo(un *unstructured.Unstructured, res *ResourceInfo, customLabel string) {
gvk := un.GroupVersionKind()
revision := resource.GetRevision(un)
if revision > 0 {
res.Info = append(res.Info, v1alpha1.InfoItem{Name: "Revision", Value: fmt.Sprintf("Rev:%v", revision)})
}
if customLabel != "" {
if labels := un.GetLabels(); labels != nil {
if value, ok := labels[customLabel]; ok {
res.Info = append(res.Info, v1alpha1.InfoItem{Name: customLabel, Value: value})
}
}
}
switch gvk.Group {
case "":
switch gvk.Kind {
Expand Down
30 changes: 15 additions & 15 deletions controller/cache/info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ func TestGetPodInfo(t *testing.T) {
`)

info := &ResourceInfo{}
populateNodeInfo(pod, info)
populateNodeInfo(pod, info, "")
assert.Equal(t, []v1alpha1.InfoItem{
{Name: "Node", Value: "minikube"},
{Name: "Containers", Value: "0/1"},
Expand Down Expand Up @@ -302,7 +302,7 @@ status:
`)

info := &ResourceInfo{}
populateNodeInfo(node, info)
populateNodeInfo(node, info, "")
assert.Equal(t, &NodeInfo{
Name: "minikube",
Capacity: v1.ResourceList{v1.ResourceMemory: resource.MustParse("6091320Ki"), v1.ResourceCPU: resource.MustParse("6")},
Expand All @@ -312,7 +312,7 @@ status:

func TestGetServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testService, info)
populateNodeInfo(testService, info, "")
assert.Equal(t, 0, len(info.Info))
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetLabels: map[string]string{"app": "guestbook"},
Expand All @@ -322,7 +322,7 @@ func TestGetServiceInfo(t *testing.T) {

func TestGetLinkAnnotatedServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testLinkAnnotatedService, info)
populateNodeInfo(testLinkAnnotatedService, info, "")
assert.Equal(t, 0, len(info.Info))
assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetLabels: map[string]string{"app": "guestbook"},
Expand All @@ -333,7 +333,7 @@ func TestGetLinkAnnotatedServiceInfo(t *testing.T) {

func TestGetIstioVirtualServiceInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIstioVirtualService, info)
populateNodeInfo(testIstioVirtualService, info, "")
assert.Equal(t, 0, len(info.Info))
require.NotNil(t, info.NetworkingInfo)
require.NotNil(t, info.NetworkingInfo.TargetRefs)
Expand Down Expand Up @@ -363,7 +363,7 @@ func TestGetIngressInfo(t *testing.T) {
}
for _, tc := range tests {
info := &ResourceInfo{}
populateNodeInfo(tc.Ingress, info)
populateNodeInfo(tc.Ingress, info, "")
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
Expand All @@ -388,7 +388,7 @@ func TestGetIngressInfo(t *testing.T) {

func TestGetLinkAnnotatedIngressInfo(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testLinkAnnotatedIngress, info)
populateNodeInfo(testLinkAnnotatedIngress, info, "")
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
Expand All @@ -412,7 +412,7 @@ func TestGetLinkAnnotatedIngressInfo(t *testing.T) {

func TestGetIngressInfoWildCardPath(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIngressWildCardPath, info)
populateNodeInfo(testIngressWildCardPath, info, "")
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
Expand All @@ -436,7 +436,7 @@ func TestGetIngressInfoWildCardPath(t *testing.T) {

func TestGetIngressInfoWithoutTls(t *testing.T) {
info := &ResourceInfo{}
populateNodeInfo(testIngressWithoutTls, info)
populateNodeInfo(testIngressWithoutTls, info, "")
assert.Equal(t, 0, len(info.Info))
sort.Slice(info.NetworkingInfo.TargetRefs, func(i, j int) bool {
return strings.Compare(info.NetworkingInfo.TargetRefs[j].Name, info.NetworkingInfo.TargetRefs[i].Name) < 0
Expand Down Expand Up @@ -481,7 +481,7 @@ func TestGetIngressInfoWithHost(t *testing.T) {
- ip: 107.178.210.11`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
Ingress: []v1.LoadBalancerIngress{{IP: "107.178.210.11"}},
Expand Down Expand Up @@ -514,7 +514,7 @@ func TestGetIngressInfoNoHost(t *testing.T) {
`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

assert.Equal(t, &v1alpha1.ResourceNetworkingInfo{
TargetRefs: []v1alpha1.ResourceRef{{
Expand Down Expand Up @@ -549,7 +549,7 @@ func TestExternalUrlWithSubPath(t *testing.T) {
- ip: 107.178.210.11`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

expectedExternalUrls := []string{"https://107.178.210.11/my/sub/path/"}
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
Expand Down Expand Up @@ -585,7 +585,7 @@ func TestExternalUrlWithMultipleSubPaths(t *testing.T) {
- ip: 107.178.210.11`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

expectedExternalUrls := []string{"https://helm-guestbook.com/my/sub/path/", "https://helm-guestbook.com/my/sub/path/2", "https://helm-guestbook.com"}
actualURLs := info.NetworkingInfo.ExternalURLs
Expand Down Expand Up @@ -615,7 +615,7 @@ func TestExternalUrlWithNoSubPath(t *testing.T) {
- ip: 107.178.210.11`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

expectedExternalUrls := []string{"https://107.178.210.11"}
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
Expand Down Expand Up @@ -643,7 +643,7 @@ func TestExternalUrlWithNetworkingApi(t *testing.T) {
- ip: 107.178.210.11`)

info := &ResourceInfo{}
populateNodeInfo(ingress, info)
populateNodeInfo(ingress, info, "")

expectedExternalUrls := []string{"https://107.178.210.11"}
assert.Equal(t, expectedExternalUrls, info.NetworkingInfo.ExternalURLs)
Expand Down
11 changes: 11 additions & 0 deletions util/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,8 @@ const (
resourceExclusionsKey = "resource.exclusions"
// resourceInclusions is the key to the list of explicitly watched resources
resourceInclusionsKey = "resource.inclusions"
// resourceCustomLabelKey is the key to a custom label to show in node info, if present
resourceCustomLabelKey = "resource.customLabel"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we support multiple labels? E.g. rename resource.customLabel to resource.customLabels and expect comma separated list of labels?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we can do that, and it's better if we do it now rather than later

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you @alexef !

better if we do it now rather than later

yeah, it is easier to support it now than migrate later.

// configManagementPluginsKey is the key to the list of config management plugins
configManagementPluginsKey = "configManagementPlugins"
// kustomizeBuildOptionsKey is a string of kustomize build parameters
Expand Down Expand Up @@ -1885,3 +1887,12 @@ func (mgr *SettingsManager) GetGlobalProjectsSettings() ([]GlobalProjectSettings
func (mgr *SettingsManager) GetNamespace() string {
return mgr.namespace
}

func (mgr *SettingsManager) GetResourceCustomLabel() (string, error) {
argoCDCM, err := mgr.getConfigMap()
if err != nil {
return "", err
}
label := argoCDCM.Data[resourceCustomLabelKey]
return label, nil
}