mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-03-06 16:38:46 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5c6608827 | ||
|
|
0564de77e6 | ||
|
|
e1eec8a9dc | ||
|
|
3d8d03f0a4 | ||
|
|
64f5c6aa85 | ||
|
|
f9e2fc9210 | ||
|
|
f9eac82928 | ||
|
|
bfbc19a583 |
@@ -666,6 +666,16 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b
|
||||
app := origApp.DeepCopy()
|
||||
|
||||
if app.Operation != nil {
|
||||
// If we get here, we are about process an operation but we cannot rely on informer since it might has stale data.
|
||||
// So always retrieve the latest version to ensure it is not stale to avoid unnecessary syncing.
|
||||
// We cannot rely on informer since applications might be updated by both application controller and api server.
|
||||
freshApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace).Get(context.Background(), app.ObjectMeta.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to retrieve latest application state: %v", err)
|
||||
return
|
||||
}
|
||||
app = freshApp
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
} else if app.DeletionTimestamp != nil && app.CascadedDeletion() {
|
||||
_, err = ctrl.finalizeApplicationDeletion(app)
|
||||
@@ -1085,7 +1095,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
|
||||
}
|
||||
|
||||
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace)
|
||||
patchedApp, err := appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
|
||||
_, err = appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
// Stop retrying updating deleted application
|
||||
if apierr.IsNotFound(err) {
|
||||
@@ -1115,10 +1125,6 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
|
||||
ctrl.auditLogger.LogAppEvent(app, eventInfo, strings.Join(messages, " "))
|
||||
ctrl.metricsServer.IncSync(app, state)
|
||||
}
|
||||
// write back to informer in order to avoid stale cache
|
||||
if err := ctrl.appInformer.GetStore().Update(patchedApp); err != nil {
|
||||
log.Warnf("Fails to update informer: %v", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1083,12 +1083,10 @@ func TestProcessRequestedAppOperation_FailedNoRetries(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1110,12 +1108,10 @@ func TestProcessRequestedAppOperation_InvalidDestination(t *testing.T) {
|
||||
fakeAppCs.Lock()
|
||||
defer fakeAppCs.Unlock()
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
}()
|
||||
|
||||
@@ -1138,12 +1134,10 @@ func TestProcessRequestedAppOperation_FailedHasRetries(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1183,12 +1177,10 @@ func TestProcessRequestedAppOperation_RunningPreviouslyFailed(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1218,12 +1210,10 @@ func TestProcessRequestedAppOperation_HasRetriesTerminated(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
- [Config Management Tools Integrations (proposal)](#config-management-tools-integrations-proposal)
|
||||
- [Argo CD Extensions (proposal)](#argo-cd-extensions-proposal)
|
||||
- [Project scoped repository and clusters (proposal)](#project-scoped-repository-and-clusters-proposal)
|
||||
- [Core Argo CD (proposal)](#core-argo-cd-aka-gitops-agent-proposal)
|
||||
- [v2.3 and beyond](#v23-and-beyond)
|
||||
- [Application Details Page Usability](#application-details-page-usability)
|
||||
- [Cluster Management User Interface](#cluster-management-user-interface)
|
||||
- [Input Forms UI Refresh](#input-forms-ui-refresh)
|
||||
- [Merge ApplicationSet controller into Argo CD](#merge-applicationset-controller-into-argo-cd)
|
||||
- [Merge Argo CD Notifications into Argo CD](#merge-argo-cd-notifications-into-argo-cd)
|
||||
- [Merge Argo CD Image Updater into Argo CD](#merge-argo-cd-image-updater-into-argo-cd)
|
||||
- [Compact Resources Tree](#compact-resources-tree)
|
||||
- [Multi-tenancy improvements](#multi-tenancy-improvements)
|
||||
- [GitOps Engine Enhancements](#gitops-engine-enhancements)
|
||||
- [Completed](#completed)
|
||||
- [✅ Core Argo CD (proposal)](#core-argo-cd-aka-gitops-agent-proposal)
|
||||
- [✅ Core Functionality Bug Fixes](#-core-functionality-bug-fixes)
|
||||
- [✅ Performance](#-performance)
|
||||
- [✅ ApplicationSet](#-applicationset)
|
||||
@@ -20,7 +24,6 @@
|
||||
- [✅ Automated Registry Monitoring](#-automated-registry-monitoring)
|
||||
- [✅ Projects Enhancements](#-projects-enhancements)
|
||||
|
||||
|
||||
## v2.2
|
||||
|
||||
### Config Management Tools Integrations ([proposal](https://github.com/argoproj/argo-cd/pull/5927))
|
||||
@@ -44,17 +47,33 @@ Instead of asking an administrator to change Argo CD settings end users can perf
|
||||
|
||||
## v2.3 and beyond
|
||||
|
||||
### Application Details Page Usability
|
||||
### Input Forms UI Refresh
|
||||
|
||||
Application details page has accumulated multiple usability and feature requests such as
|
||||
[Node view](https://github.com/argoproj/argo-cd/issues/1483),
|
||||
Network view ([1](https://github.com/argoproj/argo-cd/issues/2892), [2](https://github.com/argoproj/argo-cd/issues/2338))
|
||||
[etc](https://github.com/argoproj/argo-cd/issues/2199).
|
||||
Improved design of the input forms in Argo CD Web UI: https://www.figma.com/file/IIlsFqqmM5UhqMVul9fQNq/Argo-CD?node-id=0%3A1
|
||||
|
||||
### Cluster Management User Interface
|
||||
### Merge ApplicationSet controller into Argo CD
|
||||
|
||||
The ApplicationSet functionality is available in Argo CD out-of-the-box ([#7351](https://github.com/argoproj/argo-cd/issues/7351)).
|
||||
The Argo CD UI/CLI/API allows to manage ApplicationSet resources same as Argo CD Applications ([#7352](https://github.com/argoproj/argo-cd/issues/7352)).
|
||||
|
||||
### Merge Argo CD Notifications into Argo CD
|
||||
|
||||
The [Argo CD Notifications](https://github.com/argoproj-labs/argocd-notifications) should be merged into Argo CD and available out-of-the-box: [#7350](https://github.com/argoproj/argo-cd/issues/7350)
|
||||
|
||||
### Merge Argo CD Image Updater into Argo CD
|
||||
|
||||
The [Argo CD Image Updater](https://github.com/argoproj-labs/argocd-image-updater) should be merged into Argo CD and available out-of-the-box: [#7385](https://github.com/argoproj/argo-cd/issues/7385)
|
||||
|
||||
### Compact resources tree
|
||||
|
||||
An ability to collaps leaf resources tree to improve visualization of very large applications: [#7349](https://github.com/argoproj/argo-cd/issues/7349)
|
||||
|
||||
### Multi-tenancy improvements
|
||||
|
||||
The multi-tenancy improvements that allow end-users to create Argo CD applications using Kubernetes directly without accessing Argo CD API.
|
||||
* [Applications outside argocd namespace](https://github.com/argoproj/argo-cd/pull/6409)
|
||||
* [AppSource](https://github.com/argoproj-labs/appsource)
|
||||
|
||||
Argo CD has information about whole clusters, not just applications in it.
|
||||
We need to provide a user interface for cluster administrators that visualize cluster level resources.
|
||||
|
||||
### GitOps Engine Enhancements
|
||||
|
||||
@@ -109,7 +128,7 @@ to improve user experience.
|
||||
|
||||
To make Argo CD successful we need to build tools that enable Argo CD administrators to handle scalability and performance issues in a self-service model.
|
||||
|
||||
That includes more metrics, out of the box alerts and a cluster management user interface.
|
||||
That includes more metrics, out-of-the-box alerts and a cluster management user interface.
|
||||
|
||||
|
||||
### ✅ Argo CD Notifications
|
||||
|
||||
@@ -35,8 +35,8 @@ metadata:
|
||||
app.kubernetes.io/name: argocd-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
data:
|
||||
kustomize.buildOptions: --load_restrictor LoadRestrictionsNone
|
||||
kustomize.buildOptions.v3.9.1: --output /tmp
|
||||
kustomize.buildOptions: --load-restrictor LoadRestrictionsNone
|
||||
kustomize.buildOptions.v4.4.0: --output /tmp
|
||||
```
|
||||
## Custom Kustomize versions
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.3
|
||||
newTag: v2.1.4
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -2988,7 +2988,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3185,7 +3185,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -11,4 +11,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.3
|
||||
newTag: v2.1.4
|
||||
|
||||
@@ -11,7 +11,7 @@ patchesStrategicMerge:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.3
|
||||
newTag: v2.1.4
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/dex
|
||||
|
||||
@@ -3684,7 +3684,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -3901,7 +3901,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -4154,7 +4154,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -4350,7 +4350,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -1071,7 +1071,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -1288,7 +1288,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1541,7 +1541,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1737,7 +1737,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -3049,7 +3049,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -3230,7 +3230,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3479,7 +3479,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -3669,7 +3669,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -436,7 +436,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -617,7 +617,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -866,7 +866,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1056,7 +1056,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.3
|
||||
image: quay.io/argoproj/argocd:v2.1.4
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -2,6 +2,7 @@ import {DataLoader, Tab, Tabs} from 'argo-ui';
|
||||
import {useData} from 'argo-ui/v2';
|
||||
import * as React from 'react';
|
||||
import {EventsList, YamlEditor} from '../../../shared/components';
|
||||
import {ErrorBoundary} from '../../../shared/components/error-boundary/error-boundary';
|
||||
import {Context} from '../../../shared/context';
|
||||
import {Application, ApplicationTree, AppSourceType, Event, RepoAppDetails, ResourceNode, State, SyncStatuses} from '../../../shared/models';
|
||||
import {services} from '../../../shared/services';
|
||||
@@ -119,9 +120,9 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
title: 'More',
|
||||
key: 'extension',
|
||||
content: (
|
||||
<div>
|
||||
<ErrorBoundary message={`Something went wrong with Extension for ${state.kind}`}>
|
||||
<ExtensionComponent tree={tree} resource={state} />
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -40,6 +40,12 @@ test('getOperationType.Sync.Operation', () => {
|
||||
expect(state).toBe('Sync');
|
||||
});
|
||||
|
||||
test('getOperationType.DeleteAndRecentSync', () => {
|
||||
const state = getOperationType({metadata: {deletionTimestamp: '123'}, status: {operationState: {operation: {sync: {}}}}} as Application);
|
||||
|
||||
expect(state).toBe('Delete');
|
||||
});
|
||||
|
||||
test('getOperationType.Sync.Status', () => {
|
||||
const state = getOperationType({metadata: {}, status: {operationState: {operation: {sync: {}}}}} as Application);
|
||||
|
||||
|
||||
@@ -597,12 +597,12 @@ export const getAppOperationState = (app: appModels.Application): appModels.Oper
|
||||
|
||||
export function getOperationType(application: appModels.Application) {
|
||||
const operation = application.operation || (application.status && application.status.operationState && application.status.operationState.operation);
|
||||
if (application.metadata.deletionTimestamp && !application.operation) {
|
||||
return 'Delete';
|
||||
}
|
||||
if (operation && operation.sync) {
|
||||
return 'Sync';
|
||||
}
|
||||
if (application.metadata.deletionTimestamp) {
|
||||
return 'Delete';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export class ErrorBoundary extends React.Component<{message?: string}, {hasError: boolean}> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {hasError: false};
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: React.ErrorInfo) {
|
||||
return {hasError: true};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return <h1>{this.props.message ? this.props.message : 'Something went wrong.'}</h1>;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import {ApplicationTree, State} from '../models';
|
||||
|
||||
const extensions: {[key: string]: Extension} = {};
|
||||
const extensions: {resources: {[key: string]: Extension}} = {resources: {}};
|
||||
const cache = new Map<string, Promise<Extension>>();
|
||||
|
||||
export interface Extension {
|
||||
@@ -15,14 +15,14 @@ export interface ExtensionComponentProps {
|
||||
|
||||
export class ExtensionsService {
|
||||
public async loadResourceExtension(group: string, kind: string): Promise<Extension> {
|
||||
const key = `${group}-${kind}`;
|
||||
const key = `${group}/${kind}`;
|
||||
const res =
|
||||
cache.get(key) ||
|
||||
new Promise<Extension>((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = `extensions/${group}/${kind}/ui/extensions.js`;
|
||||
script.src = `extensions/resources/${group}/${kind}/ui/extensions.js`;
|
||||
script.onload = () => {
|
||||
const ext = extensions[key];
|
||||
const ext = extensions.resources[key];
|
||||
if (!ext) {
|
||||
reject(`Failed to load extension for ${group}/${kind}`);
|
||||
} else {
|
||||
|
||||
@@ -327,7 +327,6 @@ func TestNewFactory(t *testing.T) {
|
||||
defer addBinDirToPath.Close()
|
||||
closer := log.Debug()
|
||||
defer closer()
|
||||
|
||||
type args struct {
|
||||
url string
|
||||
insecureIgnoreHostKey bool
|
||||
@@ -337,7 +336,6 @@ func TestNewFactory(t *testing.T) {
|
||||
args args
|
||||
}{
|
||||
{"GitHub", args{url: "https://github.com/argoproj/argocd-example-apps"}},
|
||||
{"Azure", args{url: "https://jsuen0437@dev.azure.com/jsuen0437/jsuen/_git/jsuen"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user