mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-20 01:28:45 +01:00
Compare commits
15 Commits
master
...
v2.3.0-rc2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37f01f6f32 | ||
|
|
36eab6b82c | ||
|
|
793acc147f | ||
|
|
b50609c0e6 | ||
|
|
5f48ce96c6 | ||
|
|
c32460a2bc | ||
|
|
7eb1aba99b | ||
|
|
1a8139f4d6 | ||
|
|
02c03c3b26 | ||
|
|
cdb20d5060 | ||
|
|
7d7eed4932 | ||
|
|
af8c5eb07a | ||
|
|
1a476f7564 | ||
|
|
7f15389c72 | ||
|
|
1a3556e1cc |
2
.github/workflows/ci-build.yaml
vendored
2
.github/workflows/ci-build.yaml
vendored
@@ -379,7 +379,7 @@ jobs:
|
||||
- name: Download Go dependencies
|
||||
run: |
|
||||
go mod download
|
||||
go get github.com/mattn/goreman
|
||||
go install github.com/mattn/goreman@latest
|
||||
- name: Install all tools required for building & testing
|
||||
run: |
|
||||
make install-test-tools-local
|
||||
|
||||
48
.github/workflows/release.yaml
vendored
48
.github/workflows/release.yaml
vendored
@@ -95,7 +95,7 @@ jobs:
|
||||
echo "=========== BEGIN COMMIT MESSAGE ============="
|
||||
git show ${SOURCE_TAG}
|
||||
echo "============ END COMMIT MESSAGE =============="
|
||||
|
||||
|
||||
# Quite dirty hack to get the release notes from the annotated tag
|
||||
# into a temporary file.
|
||||
RELEASE_NOTES=$(mktemp -p /tmp release-notes.XXXXXX)
|
||||
@@ -197,12 +197,14 @@ jobs:
|
||||
if: ${{ env.DRY_RUN != 'true' }}
|
||||
|
||||
|
||||
- uses: docker/setup-qemu-action@v1
|
||||
- uses: docker/setup-buildx-action@v1
|
||||
- name: Build and push Docker image for release
|
||||
run: |
|
||||
set -ue
|
||||
git clean -fd
|
||||
mkdir -p dist/
|
||||
docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAMESPACE}/argocd:${TARGET_VERSION} -t argoproj/argocd:${TARGET_VERSION} .
|
||||
docker buildx build --platform linux/amd64,linux/arm64 --push -t ${IMAGE_NAMESPACE}/argocd:v${TARGET_VERSION} -t argoproj/argocd:v${TARGET_VERSION} .
|
||||
make release-cli
|
||||
chmod +x ./dist/argocd-linux-amd64
|
||||
./dist/argocd-linux-amd64 version --client
|
||||
@@ -287,6 +289,47 @@ jobs:
|
||||
asset_content_type: application/octet-stream
|
||||
if: ${{ env.DRY_RUN != 'true' }}
|
||||
|
||||
- name: Generate SBOM (spdx)
|
||||
id: spdx-builder
|
||||
env:
|
||||
# defines the spdx/spdx-sbom-generator version to use.
|
||||
SPDX_GEN_VERSION: v0.0.13
|
||||
# defines the sigs.k8s.io/bom version to use.
|
||||
SIGS_BOM_VERSION: v0.2.1
|
||||
# comma delimited list of project relative folders to inspect for package
|
||||
# managers (gomod, yarn, npm).
|
||||
PROJECT_FOLDERS: ".,./ui"
|
||||
# full qualified name of the docker image to be inspected
|
||||
DOCKER_IMAGE: ${{env.IMAGE_NAMESPACE}}/argocd:v${{env.TARGET_VERSION}}
|
||||
run: |
|
||||
go install github.com/spdx/spdx-sbom-generator/cmd/generator@$SPDX_GEN_VERSION
|
||||
go install sigs.k8s.io/bom/cmd/bom@$SIGS_BOM_VERSION
|
||||
|
||||
# Generate SPDX for project dependencies analyzing package managers
|
||||
for folder in $(echo $PROJECT_FOLDERS | sed "s/,/ /g")
|
||||
do
|
||||
generator -p $folder -o /tmp
|
||||
done
|
||||
|
||||
# Generate SPDX for binaries analyzing the docker image
|
||||
if [[ ! -z $DOCKER_IMAGE ]]; then
|
||||
bom generate -o /tmp/bom-docker-image.spdx -i $DOCKER_IMAGE
|
||||
fi
|
||||
|
||||
tar -zcf /tmp/sbom.tar.gz /tmp/*.spdx
|
||||
if: ${{ env.DRY_RUN != 'true' }}
|
||||
|
||||
- name: Upload SBOM to release assets
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: /tmp/sbom.tar.gz
|
||||
asset_name: sbom.tar.gz
|
||||
asset_content_type: application/octet-stream
|
||||
if: ${{ env.DRY_RUN != 'true' }}
|
||||
|
||||
- name: Update homebrew formula
|
||||
env:
|
||||
HOMEBREW_TOKEN: ${{ secrets.RELEASE_HOMEBREW_TOKEN }}
|
||||
@@ -301,3 +344,4 @@ jobs:
|
||||
set -ue
|
||||
git push --delete origin ${SOURCE_TAG}
|
||||
if: ${{ always() }}
|
||||
|
||||
|
||||
2
.gitpod.Dockerfile
vendored
2
.gitpod.Dockerfile
vendored
@@ -9,7 +9,7 @@ RUN curl -L https://go.kubebuilder.io/dl/2.3.1/$(go env GOOS)/$(go env GOARCH) |
|
||||
tar -xz -C /tmp/ && mv /tmp/kubebuilder_2.3.1_$(go env GOOS)_$(go env GOARCH) /usr/local/kubebuilder
|
||||
|
||||
RUN apt-get install redis-server -y
|
||||
RUN go get github.com/mattn/goreman
|
||||
RUN go install github.com/mattn/goreman@latest
|
||||
|
||||
USER gitpod
|
||||
|
||||
|
||||
@@ -2,5 +2,5 @@ image:
|
||||
file: .gitpod.Dockerfile
|
||||
|
||||
tasks:
|
||||
- init: make mod-download-local dep-ui-local && GO111MODULE=off go get github.com/mattn/goreman
|
||||
- init: make mod-download-local dep-ui-local && GO111MODULE=off go install github.com/mattn/goreman@latest
|
||||
command: make start-test-k8s
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/pkg/rand"
|
||||
@@ -68,7 +67,7 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
// Make sure the command is killed immediately on timeout. https://stackoverflow.com/a/38133948/684776
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
|
||||
cmd.SysProcAttr = newSysProcAttr(true)
|
||||
|
||||
start := time.Now()
|
||||
err = cmd.Start()
|
||||
@@ -80,7 +79,7 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
|
||||
<-ctx.Done()
|
||||
// Kill by group ID to make sure child processes are killed. The - tells `kill` that it's a group ID.
|
||||
// Since we didn't set Pgid in SysProcAttr, the group ID is the same as the process ID. https://pkg.go.dev/syscall#SysProcAttr
|
||||
_ = syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
_ = sysCallKill(-cmd.Process.Pid)
|
||||
}()
|
||||
|
||||
err = cmd.Wait()
|
||||
|
||||
16
cmpserver/plugin/plugin_unix.go
Normal file
16
cmpserver/plugin/plugin_unix.go
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{Setpgid: setpgid}
|
||||
}
|
||||
|
||||
func sysCallKill(pid int) error {
|
||||
return syscall.Kill(pid, syscall.SIGKILL)
|
||||
}
|
||||
16
cmpserver/plugin/plugin_windows.go
Normal file
16
cmpserver/plugin/plugin_windows.go
Normal file
@@ -0,0 +1,16 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func newSysProcAttr(setpgid bool) *syscall.SysProcAttr {
|
||||
return &syscall.SysProcAttr{}
|
||||
}
|
||||
|
||||
func sysCallKill(pid int) error {
|
||||
return nil
|
||||
}
|
||||
@@ -36,9 +36,6 @@ import (
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
// make sure to register workqueue prometheus metrics
|
||||
_ "k8s.io/component-base/metrics/prometheus/workqueue"
|
||||
|
||||
statecache "github.com/argoproj/argo-cd/v2/controller/cache"
|
||||
"github.com/argoproj/argo-cd/v2/controller/metrics"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application"
|
||||
|
||||
@@ -159,6 +159,7 @@ func NewMetricsServer(addr string, appLister applister.ApplicationLister, appFil
|
||||
|
||||
mux := http.NewServeMux()
|
||||
registry := NewAppRegistry(appLister, appFilter, appLabels)
|
||||
registry.MustRegister(depth, adds, latency, workDuration, unfinished, longestRunningProcessor, retries)
|
||||
mux.Handle(MetricsPath, promhttp.HandlerFor(prometheus.Gatherers{
|
||||
// contains app controller specific metrics
|
||||
registry,
|
||||
|
||||
101
controller/metrics/workqueue.go
Normal file
101
controller/metrics/workqueue.go
Normal file
@@ -0,0 +1,101 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
)
|
||||
|
||||
const (
|
||||
WorkQueueSubsystem = "workqueue"
|
||||
DepthKey = "depth"
|
||||
AddsKey = "adds_total"
|
||||
QueueLatencyKey = "queue_duration_seconds"
|
||||
WorkDurationKey = "work_duration_seconds"
|
||||
UnfinishedWorkKey = "unfinished_work_seconds"
|
||||
LongestRunningProcessorKey = "longest_running_processor_seconds"
|
||||
RetriesKey = "retries_total"
|
||||
)
|
||||
|
||||
var (
|
||||
depth = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: DepthKey,
|
||||
Help: "Current depth of workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
adds = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: AddsKey,
|
||||
Help: "Total number of adds handled by workqueue",
|
||||
}, []string{"name"})
|
||||
|
||||
latency = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: QueueLatencyKey,
|
||||
Help: "How long in seconds an item stays in workqueue before being requested",
|
||||
Buckets: []float64{1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 30, 60, 120, 180},
|
||||
}, []string{"name"})
|
||||
|
||||
workDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: WorkDurationKey,
|
||||
Help: "How long in seconds processing an item from workqueue takes.",
|
||||
Buckets: []float64{1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 30, 60, 120, 180},
|
||||
}, []string{"name"})
|
||||
|
||||
unfinished = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: UnfinishedWorkKey,
|
||||
Help: "How many seconds of work has been done that " +
|
||||
"is in progress and hasn't been observed by work_duration. Large " +
|
||||
"values indicate stuck threads. One can deduce the number of stuck " +
|
||||
"threads by observing the rate at which this increases.",
|
||||
}, []string{"name"})
|
||||
|
||||
longestRunningProcessor = prometheus.NewGaugeVec(prometheus.GaugeOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: LongestRunningProcessorKey,
|
||||
Help: "How many seconds has the longest running " +
|
||||
"processor for workqueue been running.",
|
||||
}, []string{"name"})
|
||||
|
||||
retries = prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||
Subsystem: WorkQueueSubsystem,
|
||||
Name: RetriesKey,
|
||||
Help: "Total number of retries handled by workqueue",
|
||||
}, []string{"name"})
|
||||
)
|
||||
|
||||
func init() {
|
||||
workqueue.SetProvider(workqueueMetricsProvider{})
|
||||
}
|
||||
|
||||
type workqueueMetricsProvider struct{}
|
||||
|
||||
func (workqueueMetricsProvider) NewDepthMetric(name string) workqueue.GaugeMetric {
|
||||
return depth.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewAddsMetric(name string) workqueue.CounterMetric {
|
||||
return adds.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewLatencyMetric(name string) workqueue.HistogramMetric {
|
||||
return latency.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewWorkDurationMetric(name string) workqueue.HistogramMetric {
|
||||
return workDuration.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewUnfinishedWorkSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return unfinished.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewLongestRunningProcessorSecondsMetric(name string) workqueue.SettableGaugeMetric {
|
||||
return longestRunningProcessor.WithLabelValues(name)
|
||||
}
|
||||
|
||||
func (workqueueMetricsProvider) NewRetriesMetric(name string) workqueue.CounterMetric {
|
||||
return retries.WithLabelValues(name)
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
# v2.2 to 2.3
|
||||
|
||||
## Argo CD Notifications and ApplicationSet Are Bundled into Argo CD
|
||||
|
||||
The Argo CD Notifications and ApplicationSet are part of Argo CD now. You no longer need to install them separately.
|
||||
The Notifications and ApplicationSet components are bundled into default Argo CD installation manifests.
|
||||
|
||||
The bundled manifests are drop-in replacements for the previous versions. If you are using Kustomize to bundle the manifests together then just
|
||||
remove references to https://github.com/argoproj-labs/argocd-notifications and https://github.com/argoproj-labs/applicationset. No action is required
|
||||
if you are using `kubectl apply`.
|
||||
|
||||
## Configure Additional ArgoCD Binaries
|
||||
|
||||
We have removed non-Linux ArgoCD binaries (Darwin amd64 and Windows amd64) from the image ([#7668](https://github.com/argoproj/argo-cd/pull/7668)) and the associated download buttons in the help page in the UI.
|
||||
|
||||
3
go.mod
3
go.mod
@@ -81,7 +81,6 @@ require (
|
||||
k8s.io/apimachinery v0.23.1
|
||||
k8s.io/client-go v0.23.1
|
||||
k8s.io/code-generator v0.23.1
|
||||
k8s.io/component-base v0.23.1
|
||||
k8s.io/klog/v2 v2.30.0
|
||||
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65
|
||||
k8s.io/kubectl v0.23.1
|
||||
@@ -112,7 +111,6 @@ require (
|
||||
github.com/antonmedv/expr v1.8.9 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -208,6 +206,7 @@ require (
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
k8s.io/apiserver v0.23.1 // indirect
|
||||
k8s.io/cli-runtime v0.23.1 // indirect
|
||||
k8s.io/component-base v0.23.1 // indirect
|
||||
k8s.io/component-helpers v0.23.1 // indirect
|
||||
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c // indirect
|
||||
k8s.io/kube-aggregator v0.23.1 // indirect
|
||||
|
||||
1
go.sum
1
go.sum
@@ -160,7 +160,6 @@ github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edY
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/bombsimon/logrusr/v2 v2.0.1 h1:1VgxVNQMCvjirZIYaT9JYn6sAVGVEcNtRE0y4mvaOAM=
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
set -eux -o pipefail
|
||||
|
||||
which go-junit-report || go get github.com/jstemmer/go-junit-report
|
||||
which go-junit-report || go install github.com/jstemmer/go-junit-report@latest
|
||||
|
||||
TEST_RESULTS=${TEST_RESULTS:-test-results}
|
||||
TEST_FLAGS=
|
||||
|
||||
@@ -27,23 +27,35 @@ if [ "$IMAGE_TAG" = "" ]; then
|
||||
IMAGE_TAG=latest
|
||||
fi
|
||||
|
||||
# bundle_with_addons bundles given kustomize base with either stable or latest version of addons
|
||||
function bundle_with_addons() {
|
||||
for addon in $(ls $SRCROOT/manifests/addons | grep -v README.md); do
|
||||
ADDON_BASE="latest"
|
||||
branch=$(git rev-parse --abbrev-ref HEAD)
|
||||
if [[ $branch = release-* ]]; then
|
||||
ADDON_BASE="stable"
|
||||
fi
|
||||
rm -rf $SRCROOT/manifests/_tmp-bundle && mkdir -p $SRCROOT/manifests/_tmp-bundle
|
||||
cat << EOF >> $SRCROOT/manifests/_tmp-bundle/kustomization.yaml
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- ../$1
|
||||
- ../addons/$addon/$ADDON_BASE
|
||||
EOF
|
||||
echo "${AUTOGENMSG}" > $2
|
||||
$KUSTOMIZE build $SRCROOT/manifests/_tmp-bundle >> $2
|
||||
done
|
||||
}
|
||||
|
||||
$KUSTOMIZE version
|
||||
|
||||
cd ${SRCROOT}/manifests/base && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
cd ${SRCROOT}/manifests/ha/base && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
cd ${SRCROOT}/manifests/core-install && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/cluster-install" >> "${SRCROOT}/manifests/install.yaml"
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/namespace-install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/namespace-install" >> "${SRCROOT}/manifests/namespace-install.yaml"
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/ha/install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/ha/cluster-install" >> "${SRCROOT}/manifests/ha/install.yaml"
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/ha/namespace-install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/ha/namespace-install" >> "${SRCROOT}/manifests/ha/namespace-install.yaml"
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/core-install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/core-install" >> "${SRCROOT}/manifests/core-install.yaml"
|
||||
bundle_with_addons "cluster-install" "${SRCROOT}/manifests/install.yaml"
|
||||
bundle_with_addons "namespace-install" "${SRCROOT}/manifests/namespace-install.yaml"
|
||||
bundle_with_addons "ha/cluster-install" "${SRCROOT}/manifests/ha/install.yaml"
|
||||
bundle_with_addons "ha/namespace-install" "${SRCROOT}/manifests/ha/namespace-install.yaml"
|
||||
bundle_with_addons "core-install" "${SRCROOT}/manifests/core-install.yaml"
|
||||
|
||||
1
manifests/.gitignore
vendored
Normal file
1
manifests/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
_tmp-bundle
|
||||
5
manifests/addons/README.md
Normal file
5
manifests/addons/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Addons
|
||||
|
||||
Directory contains Kustomize manifests of bundled Argo CD addons. Each directory must include the latest and stable versions
|
||||
of the installation manifests in the directories named accordingly. The stable version should point to a particular git
|
||||
tag and must be updated prior to each release.
|
||||
@@ -0,0 +1,4 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- https://raw.githubusercontent.com/argoproj/applicationset/v0.3.0/manifests/install.yaml
|
||||
@@ -5,13 +5,12 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc2
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
- ./repo-server
|
||||
- ./server
|
||||
- ./applicationset
|
||||
- ./config
|
||||
- ./redis
|
||||
- ./notification
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,4 +11,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc2
|
||||
|
||||
@@ -11,13 +11,12 @@ patchesStrategicMerge:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: latest
|
||||
newTag: v2.3.0-rc2
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/dex
|
||||
- ../../base/repo-server
|
||||
- ../../base/server
|
||||
- ../../base/applicationset
|
||||
- ../../base/config
|
||||
- ../../base/notification
|
||||
- ./redis-ha
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -132,7 +132,7 @@ func TestGenerateYamlManifestInDir(t *testing.T) {
|
||||
q := apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: &src}
|
||||
|
||||
// update this value if we add/remove manifests
|
||||
const countOfManifests = 47
|
||||
const countOfManifests = 41
|
||||
|
||||
res1, err := service.GenerateManifest(context.Background(), &q)
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ RUN ./install.sh ksonnet-linux && \
|
||||
./install.sh codegen-tools && \
|
||||
./install.sh codegen-go-tools && \
|
||||
./install.sh lint-tools && \
|
||||
go get github.com/mattn/goreman && \
|
||||
go get github.com/kisielk/godepgraph && \
|
||||
go get github.com/jstemmer/go-junit-report && \
|
||||
go install github.com/mattn/goreman@latest && \
|
||||
go install github.com/kisielk/godepgraph@latest && \
|
||||
go install github.com/jstemmer/go-junit-report@latest && \
|
||||
rm -rf /tmp/dl && \
|
||||
rm -rf /tmp/helm && \
|
||||
rm -rf /tmp/helm2 && \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FROM golang:1.17.6 AS go
|
||||
|
||||
RUN go get github.com/mattn/goreman && \
|
||||
go get github.com/kisielk/godepgraph
|
||||
RUN go install github.com/mattn/goreman@latest && \
|
||||
go install github.com/kisielk/godepgraph@latest
|
||||
|
||||
FROM ubuntu:21.10
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ To build it, run the following. Note that kustomize is required:
|
||||
|
||||
```shell
|
||||
cd test/remote
|
||||
export IMAGE_NAMESPACE=quay.io/youruser
|
||||
export IMAGE_NAMESPACE=quay.io/{YOUR USERNAME HERE}
|
||||
# builds & tags the image
|
||||
make image
|
||||
# pushes the image to your repository
|
||||
@@ -66,6 +66,8 @@ make manifests > /tmp/e2e-repositories.yaml
|
||||
If you do not have kustomize installed, you need to manually edit the manifests
|
||||
at `test/remote/manifests/e2e_repositories.yaml` to point to the correct image.
|
||||
|
||||
If you get `make: realpath: Command not found`, install coreutils.
|
||||
|
||||
### Deploy the test container and additional permissions
|
||||
|
||||
**Note:** The test container requires to be run in privileged mode for now, due
|
||||
@@ -83,7 +85,7 @@ Then, apply the manifests for the E2E repositories workload:
|
||||
kubectl -n argocd-e2e apply -f /tmp/e2e-repositories.yaml
|
||||
```
|
||||
|
||||
Verify that the deployment was succesful:
|
||||
Verify that the deployment was successful:
|
||||
|
||||
```shell
|
||||
kubectl -n argocd-e2e rollout status deployment argocd-e2e-cluster
|
||||
@@ -106,13 +108,13 @@ as the cluster, or the cluster IPs are routed to your host, you can use the
|
||||
following:
|
||||
|
||||
```shell
|
||||
export ARGOCD_SERVER=$(kubectl get svc argocd-server -o jsonpath='{.spec.clusterIP}')
|
||||
export ARGOCD_SERVER=$(kubectl -n argocd-e2e get svc argocd-server -o jsonpath='{.spec.clusterIP}')
|
||||
```
|
||||
|
||||
Set the admin password to use:
|
||||
|
||||
```shell
|
||||
export ARGOCD_E2E_ADMIN_PASSWORD=$(kubectl get secrets argocd-initial-admin-secret -o jsonpath='{.data.password}'|base64 -d)
|
||||
export ARGOCD_E2E_ADMIN_PASSWORD=$(kubectl -n argocd-e2e get secrets argocd-initial-admin-secret -o jsonpath='{.data.password}'|base64 -d)
|
||||
```
|
||||
|
||||
Run the tests
|
||||
@@ -204,7 +206,7 @@ Some environment variables can control the behavior of the tests:
|
||||
|
||||
Furthermore, you can skip various classes of tests by setting the following to true:
|
||||
|
||||
```
|
||||
```shell
|
||||
# If you disabled GPG feature, set to true to skip related tests
|
||||
export ARGOCD_E2E_SKIP_GPG=${ARGOCD_E2E_SKIP_GPG:-false}
|
||||
# Some tests do not work OOTB with OpenShift
|
||||
@@ -215,7 +217,6 @@ export ARGOCD_E2E_SKIP_HELM=${ARGOCD_E2E_SKIP_HELM:-false}
|
||||
export ARGOCD_E2E_SKIP_HELM2=${ARGOCD_E2E_SKIP_HELM2:-false}
|
||||
# Skip Ksonnet tests
|
||||
export ARGOCD_E2E_SKIP_KSONNET=${ARGOCD_E2E_SKIP_KSONNET:-false}
|
||||
|
||||
```
|
||||
|
||||
## Recording tests that ran successfully and restart at point of fail
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {Checkbox} from 'argo-ui';
|
||||
import {useData} from 'argo-ui/v2';
|
||||
import * as minimatch from 'minimatch';
|
||||
import * as React from 'react';
|
||||
import {Context} from '../../../shared/context';
|
||||
import {Application, ApplicationDestination, Cluster, HealthStatusCode, HealthStatuses, SyncStatusCode, SyncStatuses} from '../../../shared/models';
|
||||
import {AppsListPreferences, services} from '../../../shared/services';
|
||||
import {Filter, FiltersGroup} from '../filter/filter';
|
||||
@@ -13,6 +15,7 @@ export interface FilterResult {
|
||||
health: boolean;
|
||||
namespaces: boolean;
|
||||
clusters: boolean;
|
||||
favourite: boolean;
|
||||
labels: boolean;
|
||||
}
|
||||
|
||||
@@ -28,6 +31,7 @@ export function getFilterResults(applications: Application[], pref: AppsListPref
|
||||
sync: pref.syncFilter.length === 0 || pref.syncFilter.includes(app.status.sync.status),
|
||||
health: pref.healthFilter.length === 0 || pref.healthFilter.includes(app.status.health.status),
|
||||
namespaces: pref.namespacesFilter.length === 0 || pref.namespacesFilter.some(ns => app.spec.destination.namespace && minimatch(app.spec.destination.namespace, ns)),
|
||||
favourite: !pref.showFavorites || pref.favoritesAppList.includes(app.metadata.name),
|
||||
clusters:
|
||||
pref.clustersFilter.length === 0 ||
|
||||
pref.clustersFilter.some(filterString => {
|
||||
@@ -211,6 +215,23 @@ const NamespaceFilter = (props: AppFilterProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const FavoriteFilter = (props: AppFilterProps) => {
|
||||
const ctx = React.useContext(Context);
|
||||
return (
|
||||
<div className='filter'>
|
||||
<Checkbox
|
||||
checked={!!props.pref.showFavorites}
|
||||
id='favouriteFilter'
|
||||
onChange={val => {
|
||||
ctx.navigation.goto('.', {showFavorites: val}, {replace: true});
|
||||
services.viewPreferences.updatePreferences({appList: {...props.pref, showFavorites: val}});
|
||||
}}
|
||||
/>{' '}
|
||||
<label htmlFor='favouriteFilter'>FAVORITES ONLY</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ApplicationsFilter = (props: AppFilterProps) => {
|
||||
const setShown = (val: boolean) => {
|
||||
services.viewPreferences.updatePreferences({appList: {...props.pref, hideFilters: !val}});
|
||||
@@ -218,6 +239,7 @@ export const ApplicationsFilter = (props: AppFilterProps) => {
|
||||
|
||||
return (
|
||||
<FiltersGroup setShown={setShown} expanded={!props.pref.hideFilters} content={props.children}>
|
||||
<FavoriteFilter {...props} />
|
||||
<SyncFilter {...props} />
|
||||
<HealthFilter {...props} />
|
||||
<LabelsFilter {...props} />
|
||||
|
||||
@@ -172,7 +172,6 @@
|
||||
&__external-links-icon-container {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
.filters-group__panel {
|
||||
|
||||
@@ -122,6 +122,9 @@ const ViewPref = ({children}: {children: (pref: AppsListPreferences & {page: num
|
||||
.split(',')
|
||||
.filter(item => !!item);
|
||||
}
|
||||
if (params.get('showFavorites') != null) {
|
||||
viewPref.showFavorites = params.get('showFavorites') === 'true';
|
||||
}
|
||||
if (params.get('view') != null) {
|
||||
viewPref.view = params.get('view') as AppsListViewType;
|
||||
} else {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {DropDownMenu} from 'argo-ui';
|
||||
import {DataLoader, DropDownMenu, Tooltip} from 'argo-ui';
|
||||
import * as React from 'react';
|
||||
import {Key, KeybindingContext, useNav} from 'argo-ui/v2';
|
||||
import {Cluster} from '../../../shared/components';
|
||||
@@ -9,6 +9,7 @@ import * as AppUtils from '../utils';
|
||||
import {OperationState} from '../utils';
|
||||
import {ApplicationsLabels} from './applications-labels';
|
||||
import {ApplicationsSource} from './applications-source';
|
||||
import {services} from '../../../shared/services';
|
||||
require('./applications-table.scss');
|
||||
|
||||
export const ApplicationsTable = (props: {
|
||||
@@ -34,66 +35,98 @@ export const ApplicationsTable = (props: {
|
||||
return (
|
||||
<Consumer>
|
||||
{ctx => (
|
||||
<div className='applications-table argo-table-list argo-table-list--clickable'>
|
||||
{props.applications.map((app, i) => (
|
||||
<div
|
||||
key={app.metadata.name}
|
||||
className={`argo-table-list__row
|
||||
<DataLoader load={() => services.viewPreferences.getPreferences()}>
|
||||
{pref => {
|
||||
const favList = pref.appList.favoritesAppList || [];
|
||||
return (
|
||||
<div className='applications-table argo-table-list argo-table-list--clickable'>
|
||||
{props.applications.map((app, i) => (
|
||||
<div
|
||||
key={app.metadata.name}
|
||||
className={`argo-table-list__row
|
||||
applications-list__entry applications-list__entry--health-${app.status.health.status} ${selectedApp === i ? 'applications-tiles__selected' : ''}`}>
|
||||
<div className={`row applications-list__table-row`} onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {}, {event: e})}>
|
||||
<div className='columns small-4'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-3'>Project:</div>
|
||||
<div className='columns small-12 xxlarge-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-3'>Name:</div>
|
||||
<div className='columns small-12 xxlarge-9'>
|
||||
{app.metadata.name} <ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-6'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Source:</div>
|
||||
<div className='columns small-12 xxlarge-10 applications-table-source' style={{position: 'relative'}}>
|
||||
<div className='applications-table-source__link'>
|
||||
<ApplicationsSource source={app.spec.source} />
|
||||
<div
|
||||
className={`row applications-list__table-row`}
|
||||
onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {}, {event: e})}>
|
||||
<div className='columns small-4'>
|
||||
<div className='row'>
|
||||
<div className=' columns small-2'>
|
||||
<div>
|
||||
<Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
|
||||
<button
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
favList?.includes(app.metadata.name)
|
||||
? favList.splice(favList.indexOf(app.metadata.name), 1)
|
||||
: favList.push(app.metadata.name);
|
||||
services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
|
||||
}}>
|
||||
<i
|
||||
className={'fas fa-star'}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
marginRight: '7px',
|
||||
color: favList?.includes(app.metadata.name) ? '#1FBDD0' : 'grey'
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='show-for-xxlarge columns small-4'>Project:</div>
|
||||
<div className='columns small-12 xxlarge-6'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className=' columns small-2' />
|
||||
<div className='show-for-xxlarge columns small-4'>Name:</div>
|
||||
<div className='columns small-12 xxlarge-6'>{app.metadata.name}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='applications-table-source__labels'>
|
||||
<ApplicationsLabels app={app} />
|
||||
|
||||
<div className='columns small-6'>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Source:</div>
|
||||
<div className='columns small-12 xxlarge-10 applications-table-source' style={{position: 'relative'}}>
|
||||
<div className='applications-table-source__link'>
|
||||
<ApplicationsSource source={app.spec.source} />
|
||||
</div>
|
||||
<div className='applications-table-source__labels'>
|
||||
<ApplicationsLabels app={app} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Destination:</div>
|
||||
<div className='columns small-12 xxlarge-10'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />/{app.spec.destination.namespace}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-2'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> <span>{app.status.health.status}</span> <br />
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} />
|
||||
<span>{app.status.sync.status}</span> <OperationState app={app} quiet={true} />
|
||||
<DropDownMenu
|
||||
anchor={() => (
|
||||
<button className='argo-button argo-button--light argo-button--lg argo-button--short'>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
</button>
|
||||
)}
|
||||
items={[
|
||||
{title: 'Sync', action: () => props.syncApplication(app.metadata.name)},
|
||||
{title: 'Refresh', action: () => props.refreshApplication(app.metadata.name)},
|
||||
{title: 'Delete', action: () => props.deleteApplication(app.metadata.name)}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='show-for-xxlarge columns small-2'>Destination:</div>
|
||||
<div className='columns small-12 xxlarge-10'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />/{app.spec.destination.namespace}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-2'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> <span>{app.status.health.status}</span>
|
||||
<br />
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} />
|
||||
<span>{app.status.sync.status}</span> <OperationState app={app} quiet={true} />
|
||||
<DropDownMenu
|
||||
anchor={() => (
|
||||
<button className='argo-button argo-button--light argo-button--lg argo-button--short'>
|
||||
<i className='fa fa-ellipsis-v' />
|
||||
</button>
|
||||
)}
|
||||
items={[
|
||||
{title: 'Sync', action: () => props.syncApplication(app.metadata.name)},
|
||||
{title: 'Refresh', action: () => props.refreshApplication(app.metadata.name)},
|
||||
{title: 'Delete', action: () => props.deleteApplication(app.metadata.name)}
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
)}
|
||||
</Consumer>
|
||||
);
|
||||
|
||||
@@ -102,158 +102,178 @@ export const ApplicationTiles = ({applications, syncApplication, refreshApplicat
|
||||
<Consumer>
|
||||
{ctx => (
|
||||
<DataLoader load={() => services.viewPreferences.getPreferences()}>
|
||||
{pref => (
|
||||
<div className='applications-tiles argo-table-list argo-table-list--clickable row small-up-1 medium-up-2 large-up-3 xxxlarge-up-4' ref={appContainerRef}>
|
||||
{applications.map((app, i) => (
|
||||
<div key={app.metadata.name} className='column column-block'>
|
||||
<div
|
||||
ref={appRef.set ? null : appRef.ref}
|
||||
className={`argo-table-list__row applications-list__entry applications-list__entry--health-${app.status.health.status} ${
|
||||
selectedApp === i ? 'applications-tiles__selected' : ''
|
||||
}`}>
|
||||
<div className='row' onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})}>
|
||||
<div className={`columns small-12 applications-list__info qe-applications-list-${app.metadata.name}`}>
|
||||
<div className='applications-list__external-link'>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-12'>
|
||||
<i className={'icon argo-icon-' + (app.spec.source.chart != null ? 'helm' : 'git')} />
|
||||
<span className='applications-list__title'>{app.metadata.name}</span>
|
||||
{pref => {
|
||||
const favList = pref.appList.favoritesAppList || [];
|
||||
return (
|
||||
<div
|
||||
className='applications-tiles argo-table-list argo-table-list--clickable row small-up-1 medium-up-2 large-up-3 xxxlarge-up-4'
|
||||
ref={appContainerRef}>
|
||||
{applications.map((app, i) => (
|
||||
<div key={app.metadata.name} className='column column-block'>
|
||||
<div
|
||||
ref={appRef.set ? null : appRef.ref}
|
||||
className={`argo-table-list__row applications-list__entry applications-list__entry--health-${app.status.health.status} ${
|
||||
selectedApp === i ? 'applications-tiles__selected' : ''
|
||||
}`}>
|
||||
<div className='row' onClick={e => ctx.navigation.goto(`/applications/${app.metadata.name}`, {view: pref.appDetails.view}, {event: e})}>
|
||||
<div className={`columns small-12 applications-list__info qe-applications-list-${app.metadata.name}`}>
|
||||
<div className='applications-list__external-link'>
|
||||
<ApplicationURLs urls={AppUtils.getExternalUrls(app.metadata.annotations, app.status.summary.externalURLs)} />
|
||||
<Tooltip content={favList?.includes(app.metadata.name) ? 'Remove Favorite' : 'Add Favorite'}>
|
||||
<button
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
favList?.includes(app.metadata.name)
|
||||
? favList.splice(favList.indexOf(app.metadata.name), 1)
|
||||
: favList.push(app.metadata.name);
|
||||
services.viewPreferences.updatePreferences({appList: {...pref.appList, favoritesAppList: favList}});
|
||||
}}>
|
||||
<i
|
||||
className={'fas fa-star fa-lg'}
|
||||
style={{cursor: 'pointer', marginLeft: '7px', color: favList?.includes(app.metadata.name) ? '#1FBDD0' : 'grey'}}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Project:'>
|
||||
Project:
|
||||
<div className='row'>
|
||||
<div className='columns small-12'>
|
||||
<i className={'icon argo-icon-' + (app.spec.source.chart != null ? 'helm' : 'git')} />
|
||||
<span className='applications-list__title'>{app.metadata.name}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Labels:'>
|
||||
Labels:
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Project:'>
|
||||
Project:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.project}</div>
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip
|
||||
zIndex={4}
|
||||
content={
|
||||
<div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Labels:'>
|
||||
Labels:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip
|
||||
zIndex={4}
|
||||
content={
|
||||
<div>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => ({label, value: app.metadata.labels[label]}))
|
||||
.map(item => (
|
||||
<div key={item.label}>
|
||||
{item.label}={item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}>
|
||||
<span>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => ({label, value: app.metadata.labels[label]}))
|
||||
.map(item => (
|
||||
<div key={item.label}>
|
||||
{item.label}={item.value}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
}>
|
||||
<span>
|
||||
{Object.keys(app.metadata.labels || {})
|
||||
.map(label => `${label}=${app.metadata.labels[label]}`)
|
||||
.join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Status:'>
|
||||
Status:
|
||||
</div>
|
||||
<div className='columns small-9' qe-id='applications-tiles-health-status'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> {app.status.health.status}
|
||||
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} /> {app.status.sync.status}
|
||||
|
||||
<OperationState app={app} quiet={true} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Repository:'>
|
||||
Repository:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip content={app.spec.source.repoURL} zIndex={4}>
|
||||
<span>{app.spec.source.repoURL}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Target Revision:'>
|
||||
Target Revision:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.targetRevision}</div>
|
||||
</div>
|
||||
{app.spec.source.path && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Path:'>
|
||||
Path:
|
||||
.map(label => `${label}=${app.metadata.labels[label]}`)
|
||||
.join(', ')}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.path}</div>
|
||||
</div>
|
||||
)}
|
||||
{app.spec.source.chart && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Chart:'>
|
||||
Chart:
|
||||
<div className='columns small-3' title='Status:'>
|
||||
Status:
|
||||
</div>
|
||||
<div className='columns small-9' qe-id='applications-tiles-health-status'>
|
||||
<AppUtils.HealthStatusIcon state={app.status.health} /> {app.status.health.status}
|
||||
|
||||
<AppUtils.ComparisonStatusIcon status={app.status.sync.status} /> {app.status.sync.status}
|
||||
|
||||
<OperationState app={app} quiet={true} />
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.chart}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Destination:'>
|
||||
Destination:
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Repository:'>
|
||||
Repository:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Tooltip content={app.spec.source.repoURL} zIndex={4}>
|
||||
<span>{app.spec.source.repoURL}</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Target Revision:'>
|
||||
Target Revision:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.targetRevision}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Namespace:'>
|
||||
Namespace:
|
||||
{app.spec.source.path && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Path:'>
|
||||
Path:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.path}</div>
|
||||
</div>
|
||||
)}
|
||||
{app.spec.source.chart && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Chart:'>
|
||||
Chart:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.source.chart}</div>
|
||||
</div>
|
||||
)}
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Destination:'>
|
||||
Destination:
|
||||
</div>
|
||||
<div className='columns small-9'>
|
||||
<Cluster server={app.spec.destination.server} name={app.spec.destination.name} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.destination.namespace}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns applications-list__entry--actions'>
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-sync'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
syncApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-sync' /> Sync
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-refresh'
|
||||
{...AppUtils.refreshLinkAttrs(app)}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
refreshApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className={classNames('fa fa-redo', {'status-icon--spin': AppUtils.isAppRefreshing(app)})} />{' '}
|
||||
<span className='show-for-xxlarge'>Refresh</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-delete'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
deleteApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-times-circle' /> <span className='show-for-xxlarge'>Delete</span>
|
||||
</a>
|
||||
<div className='row'>
|
||||
<div className='columns small-3' title='Namespace:'>
|
||||
Namespace:
|
||||
</div>
|
||||
<div className='columns small-9'>{app.spec.destination.namespace}</div>
|
||||
</div>
|
||||
<div className='row'>
|
||||
<div className='columns applications-list__entry--actions'>
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-sync'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
syncApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-sync' /> Sync
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-refresh'
|
||||
{...AppUtils.refreshLinkAttrs(app)}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
refreshApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className={classNames('fa fa-redo', {'status-icon--spin': AppUtils.isAppRefreshing(app)})} />{' '}
|
||||
<span className='show-for-xxlarge'>Refresh</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
className='argo-button argo-button--base'
|
||||
qe-id='applications-tiles-button-delete'
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
deleteApplication(app.metadata.name);
|
||||
}}>
|
||||
<i className='fa fa-times-circle' /> <span className='show-for-xxlarge'>Delete</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</DataLoader>
|
||||
)}
|
||||
</Consumer>
|
||||
|
||||
@@ -63,6 +63,7 @@ export class AppsListPreferences {
|
||||
pref.projectsFilter = [];
|
||||
pref.reposFilter = [];
|
||||
pref.syncFilter = [];
|
||||
pref.showFavorites = false;
|
||||
}
|
||||
|
||||
public labelsFilter: string[];
|
||||
@@ -75,6 +76,8 @@ export class AppsListPreferences {
|
||||
public view: AppsListViewType;
|
||||
public hideFilters: boolean;
|
||||
public statusBarView: HealthStatusBarPreferences;
|
||||
public showFavorites: boolean;
|
||||
public favoritesAppList: string[];
|
||||
}
|
||||
|
||||
export interface ViewPreferences {
|
||||
@@ -117,6 +120,8 @@ const DEFAULT_PREFERENCES: ViewPreferences = {
|
||||
syncFilter: new Array<string>(),
|
||||
healthFilter: new Array<string>(),
|
||||
hideFilters: false,
|
||||
showFavorites: false,
|
||||
favoritesAppList: new Array<string>(),
|
||||
statusBarView: {
|
||||
showHealthStatusBar: true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user