Compare commits

...

22 Commits

Author SHA1 Message Date
argo-bot
2ccc17afcb Bump version to 2.4.10 2022-08-17 20:48:21 +00:00
argo-bot
e7521ed7b8 Bump version to 2.4.10 2022-08-17 20:48:17 +00:00
Michael Crenshaw
f83bed0d4b fix: missing actions (#10327) (#10359)
Signed-off-by: CI <michael@crenshaw.dev>

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-17 16:33:07 -04:00
JesseBot
88274b6870 docs: Add "Create Namespace" to sync options doc (#3490) (#10326)
* Add create namespace to the sync options doc

Signed-off-by: JesseBot <jessebot@linux.com>

* Update docs/user-guide/sync-options.md

Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Signed-off-by: JesseBot <jessebot@linux.com>
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>
2022-08-17 15:12:09 -04:00
jsmcnair
431ee12282 docs: Document safe concurrent processing of sidecar CMP (#10336)
Signed-off-by: jsmcnair <john.mcnair@yellowdog.co>

Signed-off-by: jsmcnair <john.mcnair@yellowdog.co>
2022-08-15 16:06:56 -04:00
Tadayuki Onishi
3b17121d44 fix: Suppressed ssh scheme url warn log (#9836)
* Fixed ssh scheme warn log degrade by #8508
Signed-off-by: kenchan0130 <tt.tanishi100@gmail.com>

* Expanded repository type getCAPath testing
Signed-off-by: kenchan0130 <tt.tanishi100@gmail.com>
2022-08-15 12:19:01 -04:00
Michael Crenshaw
f071b29b5f fix: respect ARGOCD_GIT_MODULES_ENABLED in the appset controller (#10285) (#10287)
* fix: respect ARGOCD_GIT_MODULES_ENABLED in the appset controller (#10285)

Signed-off-by: CI <michael@crenshaw.dev>

* remove duplicate line

Signed-off-by: CI <michael@crenshaw.dev>

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-12 14:47:02 -04:00
Michael Crenshaw
5ed749e827 docs: clusterResources in declarative cluster config (#10219)
* docs: clusterResources in declarative cluster config

Signed-off-by: CI <michael@crenshaw.dev>

* add article

Signed-off-by: CI <michael@crenshaw.dev>

Signed-off-by: CI <michael@crenshaw.dev>
2022-08-11 13:50:12 -04:00
argo-bot
1ba9008536 Bump version to 2.4.9 2022-08-11 15:08:32 +00:00
argo-bot
2b873f0b3a Bump version to 2.4.9 2022-08-11 15:08:25 +00:00
Michael Crenshaw
3fdb6ae960 docs: fix version reference for logs UI fix (#10245)
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-09 17:27:27 -04:00
Brandon High
d40ebce7b3 docs: Document ignoreAggregatedRoles setting (#10206)
Signed-off-by: Brandon High <highb@users.noreply.github.com>
2022-08-09 12:05:01 -04:00
César M. Cristóbal
d945e9f256 docs: fix microsoft user management mapping role (#10251)
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-09 10:17:18 -04:00
Sverre Boschman
fb75ada4c2 docs(applicationset): fix layout matrix/merge generator restrictions (#10246)
Co-authored-by: Michael Crenshaw <michael@crenshaw.dev>

Signed-off-by: Sverre Boschman <1142569+sboschman@users.noreply.github.com>
2022-08-09 10:08:15 -04:00
Kerwood
05c9ba27e3 fix: Drop all references to exec unless the feature is enabled (#9920) (#10187)
* fix:  Drop all references to exec unless the feature is enabled #9920

Signed-off-by: Patrick Kerwood <patrick@kerwood.dk>

* fixed tslint issues

Signed-off-by: Patrick Kerwood <patrick@kerwood.dk>
2022-08-08 16:33:10 -04:00
reggie-k
77c972d27e fix: UI part for logs RBAC - do not display the logs tab when no RBAC in place (#7211) (#9828)
* show logs tab only upon explicit rbac allow policy

Signed-off-by: reggie-k <reginakagan@gmail.com>

* 2.4.7 docs edit

Signed-off-by: reggie-k <reginakagan@gmail.com>
2022-08-08 16:31:11 -04:00
jannfis
7e0ee5c449 fix: Ignore non-self-referencing resources while pruning (#10198)
* fix: Ignore non-self-referencing resources while pruning

Signed-off-by: jannfis <jann@mistrust.net>
2022-08-08 17:44:12 +00:00
Sahdev Zala
164284e329 docs: correct the api field description for the GitLab example (#10081)
The api field description for the GitLab example seems mistakenly
copied from the GitHub example.

Signed-off-by: Sahdev Zala <spzala@us.ibm.com>
2022-08-05 15:24:53 -04:00
Renaud Guérin
ac2c1618b2 docs: Use ConfigMap to disable TLS (#10106)
* docs: Use ConfigMap to disable TLS

Signed-off-by: Renaud Guerin <renaud@renaudguerin.net>

* Fix typo

Signed-off-by: Renaud Guerin <renaud@renaudguerin.net>
2022-08-04 17:00:15 -04:00
my-git9
4ee796604a docs: improve Installation.md (#10173)
Signed-off-by: xin.li <xin.li@daocloud.io>
2022-08-04 10:23:20 -04:00
Yves Richard
118d4d3c58 docs: fix kustomize namePrefix misconception in application.yaml (#10162)
* Update docs/operator-manual/application.yaml

- Removed comment about what namePrefix does. (i.e. it does not add a prefix to the image)
- Added examples of other supported transformers. (based on looking at the source code)
- Added link to the kustomize docs where the transormers are described in more detail.

* Update kustomize casing to be consistent

Signed-off-by: whyvez <yves@premise.com>
2022-08-03 14:40:10 -04:00
Mohamed Iflan
912fe33009 docs: Fixed indentation Error (#10123)
* Fixed indentation Error

Signed-off-by: iflan7744 <iflan_mohamed@yahoo.com>

* Fixed indentation Error for top-level data key

Signed-off-by: iflan7744 <iflan_mohamed@yahoo.com>

Co-authored-by: iflan7744 <iflan_mohamed@yahoo.com>
Signed-off-by: CI <michael@crenshaw.dev>
2022-08-01 10:40:08 -04:00
35 changed files with 339 additions and 254 deletions

View File

@@ -13,9 +13,13 @@ commands, and helps to troubleshoot the application state.
Argo CD is used to manage the critical infrastructure of multiple organizations, which makes security the top priority of the project. We've listened to
your feedback and introduced additional access control settings that control access to Kubernetes Pod logs and the new Web Terminal feature.
#### Known UI Issue for Pod Logs Access
#### Pod Logs UI
Currently, upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
Since 2.4.9, the LOGS tab in pod view is visible in the UI only for users with explicit allow get logs policy.
#### Known pod logs UI issue prior to 2.4.9
Upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
### OpenTelemetry Tracing Integration

View File

@@ -1 +1 @@
2.4.8
2.4.10

View File

@@ -19,8 +19,9 @@ type RepositoryDB interface {
}
type argoCDService struct {
repositoriesDB RepositoryDB
storecreds git.CredsStore
repositoriesDB RepositoryDB
storecreds git.CredsStore
submoduleEnabled bool
}
type Repos interface {
@@ -32,11 +33,12 @@ type Repos interface {
GetDirectories(ctx context.Context, repoURL string, revision string) ([]string, error)
}
func NewArgoCDService(db db.ArgoDB, gitCredStore git.CredsStore, repoServerAddress string) Repos {
func NewArgoCDService(db db.ArgoDB, gitCredStore git.CredsStore, submoduleEnabled bool) Repos {
return &argoCDService{
repositoriesDB: db.(RepositoryDB),
storecreds: gitCredStore,
repositoriesDB: db.(RepositoryDB),
storecreds: gitCredStore,
submoduleEnabled: submoduleEnabled,
}
}
@@ -52,7 +54,7 @@ func (a *argoCDService) GetFiles(ctx context.Context, repoURL string, revision s
return nil, err
}
err = checkoutRepo(gitRepoClient, revision)
err = checkoutRepo(gitRepoClient, revision, a.submoduleEnabled)
if err != nil {
return nil, err
}
@@ -86,7 +88,7 @@ func (a *argoCDService) GetDirectories(ctx context.Context, repoURL string, revi
return nil, err
}
err = checkoutRepo(gitRepoClient, revision)
err = checkoutRepo(gitRepoClient, revision, a.submoduleEnabled)
if err != nil {
return nil, err
}
@@ -128,7 +130,7 @@ func (a *argoCDService) GetDirectories(ctx context.Context, repoURL string, revi
}
func checkoutRepo(gitRepoClient git.Client, revision string) error {
func checkoutRepo(gitRepoClient git.Client, revision string, submoduleEnabled bool) error {
err := gitRepoClient.Init()
if err != nil {
return fmt.Errorf("Error during initializing repo: %w", err)
@@ -143,7 +145,7 @@ func checkoutRepo(gitRepoClient git.Client, revision string) error {
if err != nil {
return fmt.Errorf("Error during fetching commitSHA: %w", err)
}
err = gitRepoClient.Checkout(commitSHA, true)
err = gitRepoClient.Checkout(commitSHA, submoduleEnabled)
if err != nil {
return fmt.Errorf("Error during repo checkout: %w", err)
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/argoproj/argo-cd/v2/applicationset/utils"
"github.com/argoproj/argo-cd/v2/common"
"github.com/argoproj/argo-cd/v2/reposerver/askpass"
"github.com/argoproj/argo-cd/v2/util/env"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -37,6 +38,11 @@ import (
argosettings "github.com/argoproj/argo-cd/v2/util/settings"
)
// TODO: load this using Cobra. https://github.com/argoproj/argo-cd/issues/10157
func getSubmoduleEnabled() bool {
return env.ParseBoolFromEnv(common.EnvGitSubmoduleEnabled, true)
}
func NewCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
@@ -136,7 +142,7 @@ func NewCommand() *cobra.Command {
terminalGenerators := map[string]generators.Generator{
"List": generators.NewListGenerator(),
"Clusters": generators.NewClusterGenerator(mgr.GetClient(), context.Background(), k8sClient, namespace),
"Git": generators.NewGitGenerator(services.NewArgoCDService(argoCDDB, askPassServer, argocdRepoServer)),
"Git": generators.NewGitGenerator(services.NewArgoCDService(argoCDDB, askPassServer, getSubmoduleEnabled())),
"SCMProvider": generators.NewSCMProviderGenerator(mgr.GetClient()),
"ClusterDecisionResource": generators.NewDuckTypeGenerator(context.Background(), dynamicClient, k8sClient, namespace),
"PullRequest": generators.NewPullRequestGenerator(mgr.GetClient()),

View File

@@ -205,6 +205,13 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
reconciliationResult.Target = patchedTargets
}
appLabelKey, err := m.settingsMgr.GetAppInstanceLabelKey()
if err != nil {
log.Errorf("Could not get appInstanceLabelKey: %v", err)
return
}
trackingMethod := argo.GetTrackingMethod(m.settingsMgr)
syncCtx, cleanup, err := sync.NewSyncContext(
compareResult.syncStatus.Revision,
reconciliationResult,
@@ -217,7 +224,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
sync.WithHealthOverride(lua.ResourceHealthOverrides(resourceOverrides)),
sync.WithPermissionValidator(func(un *unstructured.Unstructured, res *v1.APIResource) error {
if !proj.IsGroupKindPermitted(un.GroupVersionKind().GroupKind(), res.Namespaced) {
return fmt.Errorf("Resource %s:%s is not permitted in project %s.", un.GroupVersionKind().Group, un.GroupVersionKind().Kind, proj.Name)
return fmt.Errorf("resource %s:%s is not permitted in project %s", un.GroupVersionKind().Group, un.GroupVersionKind().Kind, proj.Name)
}
if res.Namespaced && !proj.IsDestinationPermitted(v1alpha1.ApplicationDestination{Namespace: un.GetNamespace(), Server: app.Spec.Destination.Server, Name: app.Spec.Destination.Name}) {
return fmt.Errorf("namespace %v is not permitted in project '%s'", un.GetNamespace(), proj.Name)
@@ -227,7 +234,9 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
sync.WithOperationSettings(syncOp.DryRun, syncOp.Prune, syncOp.SyncStrategy.Force(), syncOp.IsApplyStrategy() || len(syncOp.Resources) > 0),
sync.WithInitialState(state.Phase, state.Message, initialResourcesRes, state.StartedAt),
sync.WithResourcesFilter(func(key kube.ResourceKey, target *unstructured.Unstructured, live *unstructured.Unstructured) bool {
return len(syncOp.Resources) == 0 || argo.ContainsSyncResource(key.Name, key.Namespace, schema.GroupVersionKind{Kind: key.Kind, Group: key.Group}, syncOp.Resources)
return (len(syncOp.Resources) == 0 ||
argo.ContainsSyncResource(key.Name, key.Namespace, schema.GroupVersionKind{Kind: key.Kind, Group: key.Group}, syncOp.Resources)) &&
m.isSelfReferencedObj(live, appLabelKey, trackingMethod)
}),
sync.WithManifestValidation(!syncOp.SyncOptions.HasOption(common.SyncOptionsDisableValidation)),
sync.WithNamespaceCreation(syncOp.SyncOptions.HasOption("CreateNamespace=true"), func(un *unstructured.Unstructured) bool {

View File

@@ -69,11 +69,16 @@ spec:
kustomize:
# Optional kustomize version. Note: version must be configured in argocd-cm ConfigMap
version: v3.5.4
# Optional image name prefix
# Supported kustomize transformers. https://kubectl.docs.kubernetes.io/references/kustomize/kustomization/
namePrefix: prod-
# Optional images passed to "kustomize edit set image".
nameSuffix: -some-suffix
commonLabels:
foo: bar
commonAnnotations:
beep: boop
images:
- gcr.io/heptio-images/ks-guestbook-demo:0.2
- my-app=gcr.io/my-repo/my-app:0.1
# directory
directory:

View File

@@ -107,32 +107,33 @@ Finally, the Matrix generator will combine both sets of outputs, and produce:
## Restrictions
1. The Matrix generator currently only supports combining the outputs of only two child generators (eg does not support generating combinations for 3 or more).
1. You should specify only a single generator per array entry, eg this is not valid:
```yaml
- matrix:
generators:
- list: # (...)
git: # (...)
```
- matrix:
generators:
- list: # (...)
git: # (...)
- While this *will* be accepted by Kubernetes API validation, the controller will report an error on generation. Each generator should be specified in a separate array element, as in the examples above.
1. The Matrix generator does not currently support [`template` overrides](Template.md#generator-templates) specified on child generators, eg this `template` will not be processed:
```yaml
- matrix:
generators:
- list:
elements:
- # (...)
template: { } # Not processed
```
- matrix:
generators:
- list:
elements:
- # (...)
template: { } # Not processed
1. Combination-type generators (matrix or merge) can only be nested once. For example, this will not work:
```yaml
- matrix:
generators:
- matrix:
generators:
- matrix: # This third level is invalid.
generators:
- list:
elements:
- # (...)
```
- matrix:
generators:
- matrix:
generators:
- matrix: # This third level is invalid.
generators:
- list:
elements:
- # (...)

View File

@@ -114,31 +114,31 @@ When merged with the updated base parameters, the `values.redis` value for the p
## Restrictions
1. You should specify only a single generator per array entry. This is not valid:
```yaml
- merge:
generators:
- list: # (...)
git: # (...)
```
- merge:
generators:
- list: # (...)
git: # (...)
- While this *will* be accepted by Kubernetes API validation, the controller will report an error on generation. Each generator should be specified in a separate array element, as in the examples above.
1. The Merge generator does not support [`template` overrides](Template.md#generator-templates) specified on child generators. This `template` will not be processed:
```yaml
- merge:
generators:
- list:
elements:
- # (...)
template: { } # Not processed
```
- merge:
generators:
- list:
elements:
- # (...)
template: { } # Not processed
1. Combination-type generators (Matrix or Merge) can only be nested once. For example, this will not work:
```yaml
- merge:
generators:
- merge:
generators:
- merge: # This third level is invalid.
generators:
- list:
elements:
- # (...)
```
- merge:
generators:
- merge:
generators:
- merge: # This third level is invalid.
generators:
- list:
elements:
- # (...)

View File

@@ -76,7 +76,7 @@ spec:
gitlab:
# The base GitLab group to scan. You can either use the group id or the full namespaced path.
group: "8675309"
# For GitLab Enterprise:
# For self-hosted GitLab:
api: https://gitlab.example.com/
# If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
allBranches: true
@@ -91,7 +91,7 @@ spec:
```
* `group`: Required name of the base GitLab group to scan. If you have multiple base groups, use multiple generators.
* `api`: If using GitHub Enterprise, the URL to access it.
* `api`: If using self-hosted GitLab, the URL to access it.
* `allBranches`: By default (false) the template will only be evaluated for the default branch of each repo. If this is true, every branch of every repository will be passed to the filters. If using this flag, you likely want to use a `branchMatch` filter.
* `includeSubgroups`: By default (false) the controller will only search for repos directly in the base group. If this is true, it will recurse through all the subgroups searching for repos to scan.
* `tokenRef`: A `Secret` name and key containing the GitLab access token to use for requests. If not specified, will make anonymous requests which have a lower rate limit and can only see public repositories.

View File

@@ -4,7 +4,7 @@ Generators are responsible for generating *parameters*, which are then rendered
Generators are primarily based on the data source that they use to generate the template parameters. For example: the List generator provides a set of parameters from a *literal list*, the Cluster generator uses the *Argo CD cluster list* as a source, the Git generator uses files/directories from a *Git repository*, and so.
As of this writing there are seven generators:
As of this writing there are eight generators:
- [List generator](Generators-List.md): The List generator allows you to target Argo CD Applications to clusters based on a fixed list of cluster name/URL values.
- [Cluster generator](Generators-Cluster.md): The Cluster generator allows you to target Argo CD Applications to clusters, based on the list of clusters defined within (and managed by) Argo CD (which includes automatically responding to cluster addition/removal events from Argo CD).

View File

@@ -489,6 +489,7 @@ The secret data must include following fields:
* `name` - cluster name
* `server` - cluster api server url
* `namespaces` - optional comma-separated list of namespaces which are accessible in that cluster. Cluster level resources would be ignored if namespace list is not empty.
* `clusterResources` - optional boolean string (`"true"` or `"false"`) determining whether Argo CD can manage cluster-level resources on this cluster. This setting is used only if the list of managed namespaces is not empty.
* `config` - JSON representation of following data structure:
```yaml

View File

@@ -119,7 +119,7 @@ If the manifest generation has no side effects then requests are processed in pa
* **Multiple Helm based applications pointing to the same directory in one Git repository:** ensure that your Helm chart don't have conditional
[dependencies](https://helm.sh/docs/chart_best_practices/dependencies/#conditions-and-tags) and create `.argocd-allow-concurrency` file in chart directory.
* **Multiple Custom plugin based applications:** avoid creating temporal files during manifest generation and create `.argocd-allow-concurrency` file in app directory.
* **Multiple Custom plugin based applications:** avoid creating temporal files during manifest generation and create `.argocd-allow-concurrency` file in app directory, or use the sidecar plugin option, which processes each application using a temporary copy of the repository.
* **Multiple Kustomize applications in same repository with [parameter overrides](../user-guide/parameters.md):** sorry, no workaround for now.

View File

@@ -12,7 +12,7 @@ There are several ways how Ingress can be configured.
The Ambassador Edge Stack can be used as a Kubernetes ingress controller with [automatic TLS termination](https://www.getambassador.io/docs/latest/topics/running/tls/#host) and routing capabilities for both the CLI and the UI.
The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command. Given the `argocd` CLI includes the port number in the request `host` header, 2 Mappings are required.
The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md). Given the `argocd` CLI includes the port number in the request `host` header, 2 Mappings are required.
### Option 1: Mapping CRD for Host-based Routing
```yaml
@@ -72,7 +72,7 @@ argocd login <host>:<port> --grpc-web-root-path /argo-cd
## [Contour](https://projectcontour.io/)
The Contour ingress controller can terminate TLS ingress traffic at the edge.
The Argo CD API server should be run with TLS disabled. Edit the `argocd-server` Deployment to add the `--insecure` flag to the argocd-server container command.
The Argo CD API server should be run with TLS disabled. Edit the `argocd-server` Deployment to add the `--insecure` flag to the argocd-server container command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
It is also possible to provide an internal-only ingress path and an external-only ingress path by deploying two instances of Contour: one behind a private-subnet LoadBalancer service and one behind a public-subnet LoadBalancer service. The private Contour deployment will pick up Ingresses annotated with `kubernetes.io/ingress.class: contour-internal` and the public Contour deployment will pick up Ingresses annotated with `kubernetes.io/ingress.class: contour-external`.
@@ -164,20 +164,7 @@ spec:
The argocd-server Service needs to be annotated with `projectcontour.io/upstream-protocol.h2c: "https,443"` to wire up the gRPC protocol proxying.
The API server should then be run with TLS disabled. Edit the `argocd-server` deployment to add the
`--insecure` flag to the argocd-server command:
```yaml
spec:
template:
spec:
containers:
- name: argocd-server
command:
- /argocd-server
- --repo-server
- argocd-repo-server:8081
- --insecure
```
`--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
## [kubernetes/ingress-nginx](https://github.com/kubernetes/ingress-nginx)
@@ -319,20 +306,7 @@ spec:
```
The API server should then be run with TLS disabled. Edit the `argocd-server` deployment to add the
`--insecure` flag to the argocd-server command:
```yaml
spec:
template:
spec:
containers:
- name: argocd-server
command:
- argocd-server
- --repo-server
- argocd-repo-server:8081
- --insecure
```
`--insecure` flag to the argocd-server command, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
The obvious disadvantage to this approach is that this technique requires two separate hostnames for
the API server -- one for gRPC and the other for HTTP/HTTPS. However it allows TLS termination to
@@ -345,7 +319,7 @@ Traefik can be used as an edge router and provide [TLS](https://docs.traefik.io/
It currently has an advantage over NGINX in that it can terminate both TCP and HTTP connections _on the same port_ meaning you do not require multiple hosts or paths.
The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command.
The API server should be run with TLS disabled. Edit the `argocd-server` deployment to add the `--insecure` flag to the argocd-server command or set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
### IngressRoute CRD
```yaml
@@ -455,26 +429,9 @@ If you need detail for all the options available for these Google integrations,
### Disable internal TLS
First, to avoid internal redirection loops from HTTP to HTTPS, the API server should be run with TLS disabled. Edit the argocd-server deployment to add the --insecure flag to the argocd-server command. For this you can edit your resource live with `kubectl -n argocd edit deployments.apps argocd-server` or use a kustomize patch before installing Argo CD.
First, to avoid internal redirection loops from HTTP to HTTPS, the API server should be run with TLS disabled.
The container command should change from:
```yaml
containers:
- command:
- argocd-server
- --staticassets
- /shared/app
```
To:
```yaml
containers:
- command:
- argocd-server
- --insecure
- --staticassets
- /shared/app
```
Edit the `--insecure` flag in the `argocd-server` command of the argocd-server deployment, or simply set `server.insecure: "true"` in the `argocd-cmd-params-cm` ConfigMap [as described here](server-commands/additional-configuration-method.md).
### Creating a service

View File

@@ -32,7 +32,7 @@ Not recommended for production use. This type of installation is typically used
> Note: Argo CD CRDs are not included into [namespace-install.yaml](https://github.com/argoproj/argo-cd/blob/master/manifests/namespace-install.yaml).
> and have to be installed separately. The CRD manifests are located in the [manifests/crds](https://github.com/argoproj/argo-cd/blob/master/manifests/crds) directory.
> Use the following command to install them:
> ```bash
> ```
> kubectl apply -k https://github.com/argoproj/argo-cd/manifests/crds\?ref\=stable
> ```

View File

@@ -151,9 +151,13 @@ p, role:test-db-admins, applications, *, staging-db-admins/*, allow
p, role:test-db-admins, logs, get, staging-db-admins/*, allow
```
## Known UI issue
### Pod Logs UI
Currently, upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
Since 2.4.9, the LOGS tab in pod view is visible in the UI only for users with explicit allow get logs policy.
### Known pod logs UI issue prior to 2.4.9
Upon pressing the "LOGS" tab in pod view by users who don't have an explicit allow get logs policy, the red "unable to load data: Internal error" is received in the bottom of the screen, and "Failed to load data, please try again" is displayed.
## Test repo-server with its new dedicated Service Account

View File

@@ -36,24 +36,24 @@
1. Edit `argocd-cm` and add the following `dex.config` to the data section, replacing the `caData`, `my-argo-cd-url` and `my-login-url` your values from the Azure AD App:
data:
url: https://my-argo-cd-url
dex.config: |
logger:
url: https://my-argo-cd-url
dex.config: |
logger:
level: debug
format: json
connectors:
- type: saml
connectors:
- type: saml
id: saml
name: saml
config:
entityIssuer: https://my-argo-cd-url/api/dex/callback
ssoURL: https://my-login-url (e.g. https://login.microsoftonline.com/xxxxx/a/saml2)
caData: |
MY-BASE64-ENCODED-CERTIFICATE-DATA
redirectURI: https://my-argo-cd-url/api/dex/callback
usernameAttr: email
emailAttr: email
groupsAttr: Group
entityIssuer: https://my-argo-cd-url/api/dex/callback
ssoURL: https://my-login-url (e.g. https://login.microsoftonline.com/xxxxx/a/saml2)
caData: |
MY-BASE64-ENCODED-CERTIFICATE-DATA
redirectURI: https://my-argo-cd-url/api/dex/callback
usernameAttr: email
emailAttr: email
groupsAttr: Group
2. Edit `argocd-rbac-cm` to configure permissions, similar to example below.
- Use Azure AD `Group IDs` for assigning roles.
@@ -169,7 +169,7 @@
p, role:org-admin, repositories, update, *, allow
p, role:org-admin, repositories, delete, *, allow
g, "84ce98d1-e359-4f3b-85af-985b458de3c6", role:org-admin
scopes: '[roles, email]'
scopes: '[groups, email]'
Refer to [operator-manual/argocd-rbac-cm.yaml](https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-rbac-cm.yaml) for all of the available variables.

View File

@@ -14,7 +14,7 @@ There are two ways to install a Config Management Plugin (CMP):
1. Add the plugin config to the Argo CD ConfigMap. The repo-server container will run your plugin's commands.
This is a good option for a simple plugin that requires only a few lines of code that fit nicely in the Argo CD ConfigMap.
2. Add the plugin as a sidecar to the repo-server Pod.
This is a good option for a more complex plugin that would clutter the Argo CD ConfigMap.
This is a good option for a more complex plugin that would clutter the Argo CD ConfigMap. A copy of the repository is sent to the sidecar container as a tarball and processed individually per application, which makes it a good option for [concurrent processing of monorepos](../operator-manual/high_availability.md#enable-concurrent-processing).
### Option 1: Configure plugins via Argo CD configmap

View File

@@ -81,7 +81,7 @@ data:
- '.webhooks[]?.clientConfig.caBundle'
```
Resource customization can also be configured to ignore all differences made by a managedField.manager at the system level. The example bellow shows how to configure ArgoCD to ignore changes made by `kube-controller-manager` in `Deployment` resources.
Resource customization can also be configured to ignore all differences made by a managedField.manager at the system level. The example bellow shows how to configure Argo CD to ignore changes made by `kube-controller-manager` in `Deployment` resources.
```yaml
data:
@@ -90,7 +90,7 @@ data:
- kube-controller-manager
```
It is possible to configure ignoreDifferences to be applied to all resources in every Application managed by an ArgoCD instance. In order to do so, resource customizations can be configured like in the example bellow:
It is possible to configure ignoreDifferences to be applied to all resources in every Application managed by an Argo CD instance. In order to do so, resource customizations can be configured like in the example bellow:
```yaml
data:
@@ -116,11 +116,26 @@ data:
By default `status` field is ignored during diffing for `CustomResourceDefinition` resource. The behavior can be extended to all resources using `all` value or disabled using `none`.
### Ignoring RBAC changes made by AggregateRoles
If you are using [Aggregated ClusterRoles](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles) and don't want Argo CD to detect the `rules` changes as drift, you can set `resource.compareoptions.ignoreAggregatedRoles: true`. Then Argo CD will no longer detect these changes as an event that requires syncing.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
data:
resource.compareoptions: |
# disables status field diffing in specified resource types
ignoreAggregatedRoles: true
```
## Known Kubernetes types in CRDs (Resource limits, Volume mounts etc)
Some CRDs are re-using data structures defined in the Kubernetes source base and therefore inheriting custom
JSON/YAML marshaling. Custom marshalers might serialize CRDs in a slightly different format that causes false
positives during drift detection.
positives during drift detection.
A typical example is the `argoproj.io/Rollout` CRD that re-using `core/v1/PodSpec` data structure. Pod resource requests
might be reformatted by the custom marshaller of `IntOrString` data type:
@@ -140,7 +155,7 @@ resources:
```
The solution is to specify which CRDs fields are using built-in Kubernetes types in the `resource.customizations`
section of `argocd-cm` ConfigMap:
section of `argocd-cm` ConfigMap:
```yaml
apiVersion: v1

View File

@@ -187,3 +187,17 @@ spec:
```
The example above shows how an ArgoCD Application can be configured so it will ignore the `spec.replicas` field from the desired state (git) during the sync stage. This is achieve by calculating and pre-patching the desired state before applying it in the cluster. Note that the `RespectIgnoreDifferences` sync option is only effective when the resource is already created in the cluster. If the Application is being created and no live state exists, the desired state is applied as-is.
## Create Namespace
```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
namespace: test
spec:
syncPolicy:
syncOptions:
- CreateNamespace=true
```
The example above shows how an Argo CD Application can be configured so it will create namespaces for the Application resources if the namespaces don't exist already. Without this either declared in the Application manifest or passed in the cli via `--sync-option CreateNamespace=true`, the Application will fail to sync if the resources' namespaces do not exist.

2
go.mod
View File

@@ -9,7 +9,7 @@ require (
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
github.com/alicebob/miniredis v2.5.0+incompatible
github.com/alicebob/miniredis/v2 v2.14.2
github.com/argoproj/gitops-engine v0.7.0
github.com/argoproj/gitops-engine v0.7.1
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0
github.com/aws/aws-sdk-go v1.38.49

4
go.sum
View File

@@ -146,8 +146,8 @@ github.com/antonmedv/expr v1.8.9/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmH
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/appscode/go v0.0.0-20190808133642-1d4ef1f1c1e0/go.mod h1:iy07dV61Z7QQdCKJCIvUoDL21u6AIceRhZzyleh2ymc=
github.com/argoproj/gitops-engine v0.7.0 h1:X6W8VP9bWTe74wWxAV3i8KZ0yBmre5DU8g+GWH09FCo=
github.com/argoproj/gitops-engine v0.7.0/go.mod h1:pRgVpLW7pZqf7n3COJ7UcDepk4cI61LAcJd64Q3Jq/c=
github.com/argoproj/gitops-engine v0.7.1 h1:aqRcIyW+Fu2wGplPOwGjABTESzQs3VBvl9A4aj5JV1c=
github.com/argoproj/gitops-engine v0.7.1/go.mod h1:pRgVpLW7pZqf7n3COJ7UcDepk4cI61LAcJd64Q3Jq/c=
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320 h1:XDjtTfccs4rSOT1n+i1zV9RpxQdKky1b4YBic16E0qY=
github.com/argoproj/notifications-engine v0.3.1-0.20220430155844-567361917320/go.mod h1:R3zlopt+/juYlebQc9Jarn9vBQ2xZruWOWjUNkfGY9M=
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 h1:Cfp7rO/HpVxnwlRqJe0jHiBbZ77ZgXhB6HWlYD02Xdc=

View File

@@ -5,7 +5,7 @@ kind: Kustomization
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.4.8
newTag: v2.4.10
resources:
- ./application-controller
- ./dex

View File

@@ -9385,7 +9385,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -9615,7 +9615,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -9664,7 +9664,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -9851,7 +9851,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -12,4 +12,4 @@ resources:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.4.8
newTag: v2.4.10

View File

@@ -11,7 +11,7 @@ patchesStrategicMerge:
images:
- name: quay.io/argoproj/argocd
newName: quay.io/argoproj/argocd
newTag: v2.4.8
newTag: v2.4.10
resources:
- ../../base/application-controller
- ../../base/applicationset-controller

View File

@@ -10320,7 +10320,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -10417,7 +10417,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -10457,7 +10457,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -10714,7 +10714,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -10763,7 +10763,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -11010,7 +11010,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -11218,7 +11218,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -1244,7 +1244,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -1341,7 +1341,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -1381,7 +1381,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -1638,7 +1638,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1687,7 +1687,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1934,7 +1934,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2142,7 +2142,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -9692,7 +9692,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -9789,7 +9789,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -9829,7 +9829,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -10054,7 +10054,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -10103,7 +10103,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -10346,7 +10346,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -10548,7 +10548,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -616,7 +616,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: argocd-applicationset-controller
ports:
@@ -713,7 +713,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /shared/argocd-dex
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
name: copyutil
securityContext:
@@ -753,7 +753,7 @@ spec:
containers:
- command:
- argocd-notifications
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
tcpSocket:
@@ -978,7 +978,7 @@ spec:
value: /helm-working-dir
- name: HELM_DATA_HOME
value: /helm-working-dir
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
failureThreshold: 3
@@ -1027,7 +1027,7 @@ spec:
- -n
- /usr/local/bin/argocd
- /var/run/argocd/argocd-cmp-server
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
name: copyutil
securityContext:
allowPrivilegeEscalation: false
@@ -1270,7 +1270,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1472,7 +1472,7 @@ spec:
key: otlp.address
name: argocd-cmd-params-cm
optional: true
image: quay.io/argoproj/argocd:v2.4.8
image: quay.io/argoproj/argocd:v2.4.10
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -195,30 +195,40 @@ func (repo *Repository) GetHelmCreds() helm.Creds {
}
func getCAPath(repoURL string) string {
hostname := ""
// For git ssh protocol url without ssh://, url.Parse() will fail to parse.
// However, no warn log is output since ssh scheme url is a possible format.
if ok, _ := git.IsSSHURL(repoURL); ok {
return ""
}
hostname := ""
// url.Parse() will happily parse most things thrown at it. When the URL
// is either https or oci, we use the parsed hostname to receive the cert,
// otherwise we'll use the parsed path (OCI repos are often specified as
// hostname, without protocol).
if parsedURL, err := url.Parse(repoURL); err == nil {
if parsedURL.Scheme == "https" || parsedURL.Scheme == "oci" {
hostname = parsedURL.Host
} else if parsedURL.Scheme == "" {
hostname = parsedURL.Path
}
} else {
parsedURL, err := url.Parse(repoURL)
if err != nil {
log.Warnf("Could not parse repo URL '%s': %v", repoURL, err)
return ""
}
if parsedURL.Scheme == "https" || parsedURL.Scheme == "oci" {
hostname = parsedURL.Host
} else if parsedURL.Scheme == "" {
hostname = parsedURL.Path
}
if hostname != "" {
if caPath, err := cert.GetCertBundlePathForRepository(hostname); err == nil {
return caPath
} else {
log.Warnf("Could not get cert bundle path for repository '%s': %v", repoURL, err)
}
if hostname == "" {
log.Warnf("Could not get hostname for repository '%s'", repoURL)
return ""
}
return ""
caPath, err := cert.GetCertBundlePathForRepository(hostname)
if err != nil {
log.Warnf("Could not get cert bundle path for repository '%s': %v", repoURL, err)
return ""
}
return caPath
}
// CopySettingsFrom copies all repository settings from source to receiver

View File

@@ -2628,6 +2628,7 @@ func TestGetCAPath(t *testing.T) {
"oci://bar.example.com",
"bar.example.com",
"ssh://foo.example.com",
"git@example.com:organization/reponame.git",
"/some/invalid/thing",
"../another/invalid/thing",
"./also/invalid",

View File

@@ -2285,6 +2285,13 @@ func TestAnnotationTrackingExtraResources(t *testing.T) {
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy)).
When().
Sync("--prune").
And(func() {
// The extra configmap must not be pruned, because it's not tracked
cm, err := KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Get(context.Background(), "extra-configmap", metav1.GetOptions{})
require.NoError(t, err)
require.Equal(t, "extra-configmap", cm.Name)
}).
And(func() {
// Add a resource with an annotation that is self-referencing the
// resource.
@@ -2301,5 +2308,17 @@ func TestAnnotationTrackingExtraResources(t *testing.T) {
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
Expect(HealthIs(health.HealthStatusHealthy)).
When().
Sync("--prune").
And(func() {
// The extra configmap must be pruned now, because it's tracked
cm, err := KubeClientset.CoreV1().ConfigMaps(DeploymentNamespace()).Get(context.Background(), "other-configmap", metav1.GetOptions{})
require.Error(t, err)
require.Equal(t, "", cm.Name)
}).
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(health.HealthStatusHealthy))
}

View File

@@ -42,7 +42,17 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
const page = parseInt(new URLSearchParams(appContext.history.location.search).get('page'), 10) || 0;
const untilTimes = (new URLSearchParams(appContext.history.location.search).get('untilTimes') || '').split(',') || [];
const getResourceTabs = (node: ResourceNode, state: State, podState: State, events: Event[], extensionTabs: ResourceTabExtension[], tabs: Tab[], execEnabled: boolean) => {
const getResourceTabs = (
node: ResourceNode,
state: State,
podState: State,
events: Event[],
extensionTabs: ResourceTabExtension[],
tabs: Tab[],
execEnabled: boolean,
execAllowed: boolean,
logsAllowed: boolean
) => {
if (!node || node === undefined) {
return [];
}
@@ -78,31 +88,33 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
const onClickContainer = (group: any, i: number) => SelectNode(selectedNodeKey, group.offset + i, 'logs', appContext);
tabs = tabs.concat([
{
key: 'logs',
icon: 'fa fa-align-left',
title: 'LOGS',
content: (
<div className='application-details__tab-content-full-height'>
<PodsLogsViewer
podName={(state.kind === 'Pod' && state.metadata.name) || ''}
group={node.group}
kind={node.kind}
name={node.name}
namespace={podState.metadata.namespace}
applicationName={application.metadata.name}
containerName={AppUtils.getContainerName(podState, selectedNodeInfo.container)}
page={{number: page, untilTimes}}
setPage={pageData => appContext.navigation.goto('.', {page: pageData.number, untilTimes: pageData.untilTimes.join(',')})}
containerGroups={containerGroups}
onClickContainer={onClickContainer}
/>
</div>
)
}
]);
if (execEnabled) {
if (logsAllowed) {
tabs = tabs.concat([
{
key: 'logs',
icon: 'fa fa-align-left',
title: 'LOGS',
content: (
<div className='application-details__tab-content-full-height'>
<PodsLogsViewer
podName={(state.kind === 'Pod' && state.metadata.name) || ''}
group={node.group}
kind={node.kind}
name={node.name}
namespace={podState.metadata.namespace}
applicationName={application.metadata.name}
containerName={AppUtils.getContainerName(podState, selectedNodeInfo.container)}
page={{number: page, untilTimes}}
setPage={pageData => appContext.navigation.goto('.', {page: pageData.number, untilTimes: pageData.untilTimes.join(',')})}
containerGroups={containerGroups}
onClickContainer={onClickContainer}
/>
</div>
)
}
]);
}
if (execEnabled && execAllowed) {
tabs = tabs.concat([
{
key: 'exec',
@@ -258,8 +270,9 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
const settings = await services.authService.settings();
const execEnabled = settings.execEnabled;
return {controlledState, liveState, events, podState, execEnabled};
const logsAllowed = await services.accounts.canI('logs', 'get', application.spec.project + '/' + application.metadata.name);
const execAllowed = await services.accounts.canI('exec', 'create', application.spec.project + '/' + application.metadata.name);
return {controlledState, liveState, events, podState, execEnabled, execAllowed, logsAllowed};
}}>
{data => (
<React.Fragment>
@@ -303,7 +316,9 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
content: <ApplicationNodeInfo application={application} live={data.liveState} controlled={data.controlledState} node={selectedNode} />
}
],
data.execEnabled
data.execEnabled,
data.execAllowed,
data.logsAllowed
)}
selectedTabKey={props.tab}
onTabSelected={selected => appContext.navigation.goto('.', {tab: selected}, {replace: true})}

View File

@@ -5,8 +5,8 @@ import * as React from 'react';
import * as ReactForm from 'react-form';
import {Text} from 'react-form';
import * as moment from 'moment';
import {BehaviorSubject, from, fromEvent, merge, Observable, Observer, Subscription} from 'rxjs';
import {debounceTime} from 'rxjs/operators';
import {BehaviorSubject, combineLatest, concat, from, fromEvent, Observable, Observer, Subscription} from 'rxjs';
import {debounceTime, map} from 'rxjs/operators';
import {AppContext, Context, ContextApis} from '../../shared/context';
import {ResourceTreeNode} from './application-resource-tree/application-resource-tree';
@@ -321,7 +321,6 @@ function getActionItems(
appChanged: BehaviorSubject<appModels.Application>,
isQuickStart: boolean
): Observable<ActionMenuItem[]> {
let menuItems: Observable<ActionMenuItem[]>;
const isRoot = resource.root && nodeKey(resource.root) === nodeKey(resource);
const items: MenuItem[] = [
...((isRoot && [
@@ -355,42 +354,61 @@ function getActionItems(
action: () => appContext.apis.navigation.goto('.', {node: nodeKey(resource), tab: 'logs'}, {replace: true})
});
}
if (resource.kind === 'Pod') {
items.push({
title: 'Exec',
iconClassName: 'fa fa-terminal',
action: () => appContext.apis.navigation.goto('.', {node: nodeKey(resource), tab: 'exec'}, {replace: true})
});
}
if (isQuickStart) {
return from([items]);
}
const execAction = services.authService
.settings()
.then(async settings => {
const execAllowed = await services.accounts.canI('exec', 'create', application.spec.project + '/' + application.metadata.name);
if (resource.kind === 'Pod' && settings.execEnabled && execAllowed) {
return [
{
title: 'Exec',
iconClassName: 'fa fa-terminal',
action: async () => appContext.apis.navigation.goto('.', {node: nodeKey(resource), tab: 'exec'}, {replace: true})
} as MenuItem
];
}
return [] as MenuItem[];
})
.catch(() => [] as MenuItem[]);
const resourceActions = services.applications
.getResourceActions(application.metadata.name, resource)
.then(actions => {
return items.concat(
actions.map(action => ({
title: action.name,
disabled: !!action.disabled,
action: async () => {
try {
const confirmed = await appContext.apis.popup.confirm(`Execute '${action.name}' action?`, `Are you sure you want to execute '${action.name}' action?`);
if (confirmed) {
await services.applications.runResourceAction(application.metadata.name, resource, action.name);
return actions.map(
action =>
({
title: action.name,
disabled: !!action.disabled,
action: async () => {
try {
const confirmed = await appContext.apis.popup.confirm(
`Execute '${action.name}' action?`,
`Are you sure you want to execute '${action.name}' action?`
);
if (confirmed) {
await services.applications.runResourceAction(application.metadata.name, resource, action.name);
}
} catch (e) {
appContext.apis.notifications.show({
content: <ErrorNotification title='Unable to execute resource action' e={e} />,
type: NotificationType.Error
});
}
} catch (e) {
appContext.apis.notifications.show({
content: <ErrorNotification title='Unable to execute resource action' e={e} />,
type: NotificationType.Error
});
}
}
}))
} as MenuItem)
);
})
.catch(() => items);
menuItems = merge(from([items]), from(resourceActions));
return menuItems;
.catch(() => [] as MenuItem[]);
return combineLatest(
from([items]), // this resolves immediately
concat([[] as MenuItem[]], resourceActions), // this resolves at first to [] and then whatever the API returns
concat([[] as MenuItem[]], execAction) // this resolves at first to [] and then whatever the API returns
).pipe(map(res => ([] as MenuItem[]).concat(...res)));
}
export function renderResourceMenu(

View File

@@ -27,4 +27,8 @@ export class AccountsService {
public deleteToken(name: string, id: string): Promise<any> {
return requests.delete(`/account/${name}/token/${id}`);
}
public canI(resource: string, action: string, subresource: string): Promise<boolean> {
return requests.get(`/account/can-i/${resource}/${action}/${subresource}`).then(res => res.body.value === 'yes');
}
}