Skip to content

Commit

Permalink
feat: Add external link annotation support (#4380)
Browse files Browse the repository at this point in the history
Example implementation of #3487
  • Loading branch information
carsonoid committed Sep 30, 2020
1 parent 712df19 commit 25823a4
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 8 deletions.
10 changes: 10 additions & 0 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ const (
AnnotationValueManagedByArgoCD = "argocd.argoproj.io"
// ResourcesFinalizerName the finalizer value which we inject to finalize deletion of an application
ResourcesFinalizerName = "resources-finalizer.argocd.argoproj.io"

// AnnotationKeyLinkPrefix tells the UI to add an external link icon to the application node
// that links to the value given in the annotation.
// The annotation key must be followed by a unique identifier. Ex: link.argocd.argoproj.io/dashboard
// It's valid to have multiple annotions that match the prefix.
// Values can simply be a url or they can have
// an optional link title separated by a "|"
// Ex: "http://grafana.example.com/d/yu5UH4MMz/deployments"
// Ex: "Go to Dashboard|http://grafana.example.com/d/yu5UH4MMz/deployments"
AnnotationKeyLinkPrefix = "link.argocd.argoproj.io/"
)

// Environment variables for tuning and debugging Argo CD
Expand Down
17 changes: 16 additions & 1 deletion controller/cache/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cache

import (
"fmt"
"strings"

"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/argoproj/gitops-engine/pkg/utils/text"
Expand All @@ -10,6 +11,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
k8snode "k8s.io/kubernetes/pkg/util/node"

"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/resource"
)
Expand Down Expand Up @@ -37,6 +39,15 @@ func populateNodeInfo(un *unstructured.Unstructured, res *ResourceInfo) {
return
}
}

for k, v := range un.GetAnnotations() {
if strings.HasPrefix(k, common.AnnotationKeyLinkPrefix) {
if res.NetworkingInfo == nil {
res.NetworkingInfo = &v1alpha1.ResourceNetworkingInfo{}
}
res.NetworkingInfo.ExternalURLs = append(res.NetworkingInfo.ExternalURLs, v)
}
}
}

func getIngress(un *unstructured.Unstructured) []v1.LoadBalancerIngress {
Expand Down Expand Up @@ -142,7 +153,11 @@ func populateIngressInfo(un *unstructured.Unstructured, res *ResourceInfo) {
for target := range targetsMap {
targets = append(targets, target)
}
urls := make([]string, 0)

var urls []string
if res.NetworkingInfo != nil {
urls = res.NetworkingInfo.ExternalURLs
}
for url := range urlsSet {
urls = append(urls, url)
}
Expand Down
47 changes: 40 additions & 7 deletions ui/src/app/applications/components/application-urls.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,56 @@
import {DropDownMenu} from 'argo-ui';
import * as React from 'react';

class ExternalLink {
public title: string;
public ref: string;

constructor(url: string) {
const parts = url.split('|');
if (parts.length === 2) {
this.title = parts[0];
this.ref = parts[1];
} else {
this.title = url;
this.ref = url;
}
}
}

export const ApplicationURLs = ({urls}: {urls: string[]}) => {
(urls || []).sort();
const externalLinks: ExternalLink[] = [];
for (const url of urls || []) {
externalLinks.push(new ExternalLink(url));
}

// sorted alphabetically & links with titles first
externalLinks.sort((a, b) => {
if (a.title !== '' && b.title !== '') {
return a.title > b.title ? 1 : -1;
} else if (a.title === '') {
return 1;
} else if (b.title === '') {
return -1;
}
return a.ref > b.ref ? 1 : -1;
});

return (
((urls || []).length > 0 && (
((externalLinks || []).length > 0 && (
<span>
<a
title={externalLinks[0].title}
onClick={e => {
e.stopPropagation();
window.open(urls[0]);
window.open(externalLinks[0].ref);
}}>
<i className='fa fa-external-link-alt' />{' '}
{urls.length > 1 && (
{externalLinks.length > 1 && (
<DropDownMenu
anchor={() => <i className='fa fa-caret-down' />}
items={urls.map(item => ({
title: item,
action: () => window.open(item)
items={externalLinks.map(item => ({
title: item.title,
action: () => window.open(item.ref)
}))}
/>
)}
Expand Down

0 comments on commit 25823a4

Please sign in to comment.