mirror of
https://github.com/argoproj/argo-cd
synced 2026-04-21 17:07:16 +00:00
Merge branch 'master' into issue-26760
This commit is contained in:
commit
aa2be31d0f
44 changed files with 945 additions and 442 deletions
4
.github/workflows/ci-build.yaml
vendored
4
.github/workflows/ci-build.yaml
vendored
|
|
@ -373,12 +373,12 @@ jobs:
|
|||
run: |
|
||||
rm -rf ui/node_modules/argo-ui/node_modules
|
||||
- name: Get e2e code coverage
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: e2e-code-coverage
|
||||
path: e2e-code-coverage
|
||||
- name: Get unit test code coverage
|
||||
uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:25.10@sha256:4a9232cc47bf99defcc8860ef62
|
|||
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
|
||||
# Also used as the image in CI jobs so needs all dependencies
|
||||
####################################################################################################
|
||||
FROM docker.io/library/golang:1.26.0@sha256:b39810f6440772ab1ddaf193aa0c2a2bbddebf7a877f127c113b103e48fd8139 AS builder
|
||||
FROM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84 AS builder
|
||||
|
||||
WORKDIR /tmp
|
||||
|
||||
|
|
@ -110,7 +110,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
|
|||
####################################################################################################
|
||||
# Argo CD Build stage which performs the actual build of Argo CD binaries
|
||||
####################################################################################################
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26.0@sha256:b39810f6440772ab1ddaf193aa0c2a2bbddebf7a877f127c113b103e48fd8139 AS argocd-build
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84 AS argocd-build
|
||||
|
||||
WORKDIR /go/src/github.com/argoproj/argo-cd
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM docker.io/library/golang:1.26.0@sha256:b39810f6440772ab1ddaf193aa0c2a2bbddebf7a877f127c113b103e48fd8139
|
||||
FROM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
|
|
|
|||
4
Tiltfile
4
Tiltfile
|
|
@ -1,6 +1,10 @@
|
|||
load('ext://restart_process', 'docker_build_with_restart')
|
||||
load('ext://uibutton', 'cmd_button', 'location')
|
||||
|
||||
# tilt version should be >= v0.37.0 for k8s_server_side_apply tilt-dev/tilt#6680
|
||||
update_settings(
|
||||
k8s_server_side_apply="true",
|
||||
)
|
||||
# add ui button in web ui to run make codegen-local (top nav)
|
||||
cmd_button(
|
||||
'make codegen-local',
|
||||
|
|
|
|||
|
|
@ -10,16 +10,19 @@ import (
|
|||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/arn"
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/codecommit"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
rgsatypes "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi/types"
|
||||
"github.com/aws/aws-sdk-go-v2/service/sts"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/aws/arn"
|
||||
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"
|
||||
"github.com/aws/aws-sdk-go-v2/service/codecommit"
|
||||
codecommittypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types"
|
||||
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/config"
|
||||
|
||||
application "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
|
|
@ -32,16 +35,16 @@ const (
|
|||
// AWSCodeCommitClient is a lean facade to the codecommitiface.CodeCommitAPI
|
||||
// it helps to reduce the mockery generated code.
|
||||
type AWSCodeCommitClient interface {
|
||||
ListRepositoriesWithContext(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) (*codecommit.ListRepositoriesOutput, error)
|
||||
GetRepositoryWithContext(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) (*codecommit.GetRepositoryOutput, error)
|
||||
ListBranchesWithContext(aws.Context, *codecommit.ListBranchesInput, ...request.Option) (*codecommit.ListBranchesOutput, error)
|
||||
GetFolderWithContext(aws.Context, *codecommit.GetFolderInput, ...request.Option) (*codecommit.GetFolderOutput, error)
|
||||
ListRepositories(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)
|
||||
GetRepository(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)
|
||||
ListBranches(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)
|
||||
GetFolder(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)
|
||||
}
|
||||
|
||||
// AWSTaggingClient is a lean facade to the resourcegroupstaggingapiiface.ResourceGroupsTaggingAPIAPI
|
||||
// it helps to reduce the mockery generated code.
|
||||
type AWSTaggingClient interface {
|
||||
GetResourcesWithContext(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)
|
||||
GetResources(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)
|
||||
}
|
||||
|
||||
type AWSCodeCommitProvider struct {
|
||||
|
|
@ -73,7 +76,7 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
|
|||
}
|
||||
|
||||
for _, repoName := range repoNames {
|
||||
repo, err := p.codeCommitClient.GetRepositoryWithContext(ctx, &codecommit.GetRepositoryInput{
|
||||
repo, err := p.codeCommitClient.GetRepository(ctx, &codecommit.GetRepositoryInput{
|
||||
RepositoryName: aws.String(repoName),
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -85,7 +88,7 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
|
|||
log.Warnf("codecommit returned invalid response for repository %s, skipped", repoName)
|
||||
continue
|
||||
}
|
||||
if aws.StringValue(repo.RepositoryMetadata.DefaultBranch) == "" {
|
||||
if aws.ToString(repo.RepositoryMetadata.DefaultBranch) == "" {
|
||||
// if a codecommit repo doesn't have default branch, it's uninitialized. not going to bother with it.
|
||||
log.Warnf("repository %s does not have default branch, skipped", repoName)
|
||||
continue
|
||||
|
|
@ -94,11 +97,11 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
|
|||
switch cloneProtocol {
|
||||
// default to SSH if unspecified (i.e. if "").
|
||||
case "", "ssh":
|
||||
url = aws.StringValue(repo.RepositoryMetadata.CloneUrlSsh)
|
||||
url = aws.ToString(repo.RepositoryMetadata.CloneUrlSsh)
|
||||
case "https":
|
||||
url = aws.StringValue(repo.RepositoryMetadata.CloneUrlHttp)
|
||||
url = aws.ToString(repo.RepositoryMetadata.CloneUrlHttp)
|
||||
case "https-fips":
|
||||
url, err = getCodeCommitFIPSEndpoint(aws.StringValue(repo.RepositoryMetadata.CloneUrlHttp))
|
||||
url, err = getCodeCommitFIPSEndpoint(aws.ToString(repo.RepositoryMetadata.CloneUrlHttp))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("https-fips is provided but repoUrl can't be transformed to FIPS endpoint: %w", err)
|
||||
}
|
||||
|
|
@ -108,13 +111,13 @@ func (p *AWSCodeCommitProvider) ListRepos(ctx context.Context, cloneProtocol str
|
|||
repos = append(repos, &Repository{
|
||||
// there's no "organization" level at codecommit.
|
||||
// we are just using AWS accountId for now.
|
||||
Organization: aws.StringValue(repo.RepositoryMetadata.AccountId),
|
||||
Repository: aws.StringValue(repo.RepositoryMetadata.RepositoryName),
|
||||
Organization: aws.ToString(repo.RepositoryMetadata.AccountId),
|
||||
Repository: aws.ToString(repo.RepositoryMetadata.RepositoryName),
|
||||
URL: url,
|
||||
Branch: aws.StringValue(repo.RepositoryMetadata.DefaultBranch),
|
||||
Branch: aws.ToString(repo.RepositoryMetadata.DefaultBranch),
|
||||
// we could propagate repo tag keys, but without value not sure if it's any useful.
|
||||
Labels: []string{},
|
||||
RepositoryId: aws.StringValue(repo.RepositoryMetadata.RepositoryId),
|
||||
RepositoryId: aws.ToString(repo.RepositoryMetadata.RepositoryId),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -142,13 +145,9 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
|
|||
FolderPath: aws.String(parentPath),
|
||||
RepositoryName: aws.String(repo.Repository),
|
||||
}
|
||||
output, err := p.codeCommitClient.GetFolderWithContext(ctx, input)
|
||||
output, err := p.codeCommitClient.GetFolder(ctx, input)
|
||||
if err != nil {
|
||||
if hasAwsError(err,
|
||||
codecommit.ErrCodeRepositoryDoesNotExistException,
|
||||
codecommit.ErrCodeCommitDoesNotExistException,
|
||||
codecommit.ErrCodeFolderDoesNotExistException,
|
||||
) {
|
||||
if hasAwsError(err) {
|
||||
return false, nil
|
||||
}
|
||||
// unhandled exception, propagate out
|
||||
|
|
@ -157,22 +156,22 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
|
|||
|
||||
// anything that matches.
|
||||
for _, submodule := range output.SubModules {
|
||||
if basePath == aws.StringValue(submodule.RelativePath) {
|
||||
if basePath == aws.ToString(submodule.RelativePath) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, subpath := range output.SubFolders {
|
||||
if basePath == aws.StringValue(subpath.RelativePath) {
|
||||
if basePath == aws.ToString(subpath.RelativePath) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, subpath := range output.Files {
|
||||
if basePath == aws.StringValue(subpath.RelativePath) {
|
||||
if basePath == aws.ToString(subpath.RelativePath) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, subpath := range output.SymbolicLinks {
|
||||
if basePath == aws.StringValue(subpath.RelativePath) {
|
||||
if basePath == aws.ToString(subpath.RelativePath) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
|
@ -182,7 +181,7 @@ func (p *AWSCodeCommitProvider) RepoHasPath(ctx context.Context, repo *Repositor
|
|||
func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repository) ([]*Repository, error) {
|
||||
repos := make([]*Repository, 0)
|
||||
if !p.allBranches {
|
||||
output, err := p.codeCommitClient.GetRepositoryWithContext(ctx, &codecommit.GetRepositoryInput{
|
||||
output, err := p.codeCommitClient.GetRepository(ctx, &codecommit.GetRepositoryInput{
|
||||
RepositoryName: aws.String(repo.Repository),
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -192,7 +191,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
|
|||
Organization: repo.Organization,
|
||||
Repository: repo.Repository,
|
||||
URL: repo.URL,
|
||||
Branch: aws.StringValue(output.RepositoryMetadata.DefaultBranch),
|
||||
Branch: aws.ToString(output.RepositoryMetadata.DefaultBranch),
|
||||
RepositoryId: repo.RepositoryId,
|
||||
Labels: repo.Labels,
|
||||
// getting SHA of the branch requires a separate GetBranch call.
|
||||
|
|
@ -204,7 +203,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
|
|||
RepositoryName: aws.String(repo.Repository),
|
||||
}
|
||||
for {
|
||||
output, err := p.codeCommitClient.ListBranchesWithContext(ctx, input)
|
||||
output, err := p.codeCommitClient.ListBranches(ctx, input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -213,7 +212,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
|
|||
Organization: repo.Organization,
|
||||
Repository: repo.Repository,
|
||||
URL: repo.URL,
|
||||
Branch: aws.StringValue(branch),
|
||||
Branch: branch,
|
||||
RepositoryId: repo.RepositoryId,
|
||||
Labels: repo.Labels,
|
||||
// getting SHA of the branch requires a separate GetBranch call.
|
||||
|
|
@ -222,7 +221,7 @@ func (p *AWSCodeCommitProvider) GetBranches(ctx context.Context, repo *Repositor
|
|||
})
|
||||
}
|
||||
input.NextToken = output.NextToken
|
||||
if aws.StringValue(output.NextToken) == "" {
|
||||
if aws.ToString(output.NextToken) == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -241,32 +240,32 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
|
|||
listReposInput := &codecommit.ListRepositoriesInput{}
|
||||
var output *codecommit.ListRepositoriesOutput
|
||||
for {
|
||||
output, err = p.codeCommitClient.ListRepositoriesWithContext(ctx, listReposInput)
|
||||
output, err = p.codeCommitClient.ListRepositories(ctx, listReposInput)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
for _, repo := range output.Repositories {
|
||||
repoNames = append(repoNames, aws.StringValue(repo.RepositoryName))
|
||||
repoNames = append(repoNames, aws.ToString(repo.RepositoryName))
|
||||
}
|
||||
listReposInput.NextToken = output.NextToken
|
||||
if aws.StringValue(output.NextToken) == "" {
|
||||
if aws.ToString(output.NextToken) == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Debugf("tag filer is specified, calling tagging api to list repos")
|
||||
discoveryInput := &resourcegroupstaggingapi.GetResourcesInput{
|
||||
ResourceTypeFilters: aws.StringSlice([]string{resourceTypeCodeCommitRepository}),
|
||||
ResourceTypeFilters: []string{resourceTypeCodeCommitRepository},
|
||||
TagFilters: tagFilters,
|
||||
}
|
||||
var output *resourcegroupstaggingapi.GetResourcesOutput
|
||||
for {
|
||||
output, err = p.taggingClient.GetResourcesWithContext(ctx, discoveryInput)
|
||||
output, err = p.taggingClient.GetResources(ctx, discoveryInput)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
for _, resource := range output.ResourceTagMappingList {
|
||||
repoArn := aws.StringValue(resource.ResourceARN)
|
||||
repoArn := aws.ToString(resource.ResourceARN)
|
||||
log.Debugf("discovered codecommit repo with arn %s", repoArn)
|
||||
repoName, extractErr := getCodeCommitRepoName(repoArn)
|
||||
if extractErr != nil {
|
||||
|
|
@ -276,7 +275,7 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
|
|||
repoNames = append(repoNames, repoName)
|
||||
}
|
||||
discoveryInput.PaginationToken = output.PaginationToken
|
||||
if aws.StringValue(output.PaginationToken) == "" {
|
||||
if aws.ToString(output.PaginationToken) == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -284,19 +283,20 @@ func (p *AWSCodeCommitProvider) listRepoNames(ctx context.Context) ([]string, er
|
|||
return repoNames, err
|
||||
}
|
||||
|
||||
func (p *AWSCodeCommitProvider) getTagFilters() []*resourcegroupstaggingapi.TagFilter {
|
||||
filters := make(map[string]*resourcegroupstaggingapi.TagFilter)
|
||||
// getTagFilters filters by tag
|
||||
func (p *AWSCodeCommitProvider) getTagFilters() []rgsatypes.TagFilter {
|
||||
filters := make(map[string]rgsatypes.TagFilter)
|
||||
for _, tagFilter := range p.tagFilters {
|
||||
filter, hasKey := filters[tagFilter.Key]
|
||||
if !hasKey {
|
||||
filter = &resourcegroupstaggingapi.TagFilter{
|
||||
filter := filters[tagFilter.Key]
|
||||
if filter.Key == nil {
|
||||
filter = rgsatypes.TagFilter{
|
||||
Key: aws.String(tagFilter.Key),
|
||||
}
|
||||
filters[tagFilter.Key] = filter
|
||||
}
|
||||
if tagFilter.Value != "" {
|
||||
filter.Values = append(filter.Values, aws.String(tagFilter.Value))
|
||||
filter.Values = append(filter.Values, tagFilter.Value)
|
||||
}
|
||||
filters[tagFilter.Key] = filter
|
||||
}
|
||||
return slices.Collect(maps.Values(filters))
|
||||
}
|
||||
|
|
@ -326,12 +326,15 @@ func getCodeCommitFIPSEndpoint(repoURL string) (string, error) {
|
|||
return strings.Replace(repoURL, prefixGitURLHTTPS, prefixGitURLHTTPSFIPS, 1), nil
|
||||
}
|
||||
|
||||
func hasAwsError(err error, codes ...string) bool {
|
||||
var awsErr awserr.Error
|
||||
if errors.As(err, &awsErr) {
|
||||
return slices.Contains(codes, awsErr.Code())
|
||||
}
|
||||
return false
|
||||
func hasAwsError(err error) bool {
|
||||
// Check for common CodeCommit exceptions using SDK v2 typed errors
|
||||
var repoNotFound *codecommittypes.RepositoryDoesNotExistException
|
||||
var commitNotFound *codecommittypes.CommitDoesNotExistException
|
||||
var folderNotFound *codecommittypes.FolderDoesNotExistException
|
||||
|
||||
return errors.As(err, &repoNotFound) ||
|
||||
errors.As(err, &commitNotFound) ||
|
||||
errors.As(err, &folderNotFound)
|
||||
}
|
||||
|
||||
// toAbsolutePath transforms a path input to absolute path, as required by AWS CodeCommit
|
||||
|
|
@ -343,37 +346,32 @@ func toAbsolutePath(path string) string {
|
|||
return filepath.ToSlash(filepath.Join("/", path)) //nolint:gocritic // Prepend slash to have an absolute path
|
||||
}
|
||||
|
||||
func createAWSDiscoveryClients(_ context.Context, role string, region string) (*resourcegroupstaggingapi.ResourceGroupsTaggingAPI, *codecommit.CodeCommit, error) {
|
||||
podSession, err := session.NewSession()
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating new AWS pod session: %w", err)
|
||||
}
|
||||
discoverySession := podSession
|
||||
// assume role if provided - this allows cross account CodeCommit repo discovery.
|
||||
if role != "" {
|
||||
log.Debugf("role %s is provided for AWS CodeCommit discovery", role)
|
||||
assumeRoleCreds := stscreds.NewCredentials(podSession, role)
|
||||
discoverySession, err = session.NewSession(&aws.Config{
|
||||
Credentials: assumeRoleCreds,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating new AWS discovery session: %w", err)
|
||||
}
|
||||
} else {
|
||||
log.Debugf("role is not provided for AWS CodeCommit discovery, using pod role")
|
||||
}
|
||||
// use region explicitly if provided - this allows cross region CodeCommit repo discovery.
|
||||
// createAWSDiscoveryClients creates AWS clients
|
||||
func createAWSDiscoveryClients(ctx context.Context, role string, region string) (*resourcegroupstaggingapi.Client, *codecommit.Client, error) {
|
||||
var configOpts []func(*config.LoadOptions) error
|
||||
if region != "" {
|
||||
log.Debugf("region %s is provided for AWS CodeCommit discovery", region)
|
||||
discoverySession = discoverySession.Copy(&aws.Config{
|
||||
Region: aws.String(region),
|
||||
})
|
||||
configOpts = append(configOpts, config.WithRegion(region))
|
||||
} else {
|
||||
log.Debugf("region is not provided for AWS CodeCommit discovery, using pod region")
|
||||
}
|
||||
// Load the default config based on config options
|
||||
cfg, err := config.LoadDefaultConfig(ctx, configOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error loading default config: %w", err)
|
||||
}
|
||||
client := sts.NewFromConfig(cfg)
|
||||
// assume role if provided - this allows cross account CodeCommit repo discovery.
|
||||
if role != "" {
|
||||
log.Debugf("role %s is provided for AWS CodeCommit discovery", role)
|
||||
assumeRoleCreds := stscreds.NewAssumeRoleProvider(client, role)
|
||||
cfg.Credentials = aws.NewCredentialsCache(assumeRoleCreds)
|
||||
} else {
|
||||
log.Debugf("role is not provided for AWS CodeCommit discovery, using pod role")
|
||||
}
|
||||
|
||||
taggingClient := resourcegroupstaggingapi.New(discoverySession)
|
||||
codeCommitClient := codecommit.New(discoverySession)
|
||||
taggingClient := resourcegroupstaggingapi.NewFromConfig(cfg)
|
||||
codeCommitClient := codecommit.NewFromConfig(cfg)
|
||||
|
||||
return taggingClient, codeCommitClient, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,13 @@ import (
|
|||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/codecommit"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/codecommit"
|
||||
codecommittypes "github.com/aws/aws-sdk-go-v2/service/codecommit/types"
|
||||
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
|
||||
rgsatypes "github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi/types"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
|
|
@ -34,7 +37,7 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
repositories []*awsCodeCommitTestRepository
|
||||
cloneProtocol string
|
||||
tagFilters []*v1alpha1.TagFilter
|
||||
expectTagFilters []*resourcegroupstaggingapi.TagFilter
|
||||
expectTagFilters []rgsatypes.TagFilter
|
||||
listRepositoryError error
|
||||
expectOverallError bool
|
||||
expectListAtCodeCommit bool
|
||||
|
|
@ -57,8 +60,8 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
{Key: "key1", Value: "value2"},
|
||||
{Key: "key2"},
|
||||
},
|
||||
expectTagFilters: []*resourcegroupstaggingapi.TagFilter{
|
||||
{Key: aws.String("key1"), Values: aws.StringSlice([]string{"value1", "value2"})},
|
||||
expectTagFilters: []rgsatypes.TagFilter{
|
||||
{Key: aws.String("key1"), Values: []string{"value1", "value2"}},
|
||||
{Key: aws.String("key2")},
|
||||
},
|
||||
expectOverallError: false,
|
||||
|
|
@ -80,7 +83,7 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
tagFilters: []*v1alpha1.TagFilter{
|
||||
{Key: "key1"},
|
||||
},
|
||||
expectTagFilters: []*resourcegroupstaggingapi.TagFilter{
|
||||
expectTagFilters: []rgsatypes.TagFilter{
|
||||
{Key: aws.String("key1")},
|
||||
},
|
||||
expectOverallError: false,
|
||||
|
|
@ -160,12 +163,12 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
codeCommitClient := mocks.NewAWSCodeCommitClient(t)
|
||||
taggingClient := mocks.NewAWSTaggingClient(t)
|
||||
ctx := t.Context()
|
||||
codecommitRepoNameIdPairs := make([]*codecommit.RepositoryNameIdPair, 0)
|
||||
resourceTaggings := make([]*resourcegroupstaggingapi.ResourceTagMapping, 0)
|
||||
codecommitRepoNameIdPairs := make([]codecommittypes.RepositoryNameIdPair, 0)
|
||||
resourceTaggings := make([]rgsatypes.ResourceTagMapping, 0)
|
||||
validRepositories := make([]*awsCodeCommitTestRepository, 0)
|
||||
|
||||
for _, repo := range testCase.repositories {
|
||||
repoMetadata := &codecommit.RepositoryMetadata{
|
||||
repoMetadata := &codecommittypes.RepositoryMetadata{
|
||||
AccountId: aws.String(repo.accountId),
|
||||
Arn: aws.String(repo.arn),
|
||||
CloneUrlHttp: aws.String("https://git-codecommit.us-east-1.amazonaws.com/v1/repos/" + repo.name),
|
||||
|
|
@ -177,13 +180,13 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
if repo.getRepositoryNilMetadata {
|
||||
repoMetadata = nil
|
||||
}
|
||||
codeCommitClient.EXPECT().GetRepositoryWithContext(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(repo.name)}).
|
||||
codeCommitClient.EXPECT().GetRepository(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(repo.name)}).
|
||||
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: repoMetadata}, repo.getRepositoryError).Maybe()
|
||||
codecommitRepoNameIdPairs = append(codecommitRepoNameIdPairs, &codecommit.RepositoryNameIdPair{
|
||||
codecommitRepoNameIdPairs = append(codecommitRepoNameIdPairs, codecommittypes.RepositoryNameIdPair{
|
||||
RepositoryId: aws.String(repo.id),
|
||||
RepositoryName: aws.String(repo.name),
|
||||
})
|
||||
resourceTaggings = append(resourceTaggings, &resourcegroupstaggingapi.ResourceTagMapping{
|
||||
resourceTaggings = append(resourceTaggings, rgsatypes.ResourceTagMapping{
|
||||
ResourceARN: aws.String(repo.arn),
|
||||
})
|
||||
if repo.valid {
|
||||
|
|
@ -192,14 +195,14 @@ func TestAWSCodeCommitListRepos(t *testing.T) {
|
|||
}
|
||||
|
||||
if testCase.expectListAtCodeCommit {
|
||||
codeCommitClient.EXPECT().ListRepositoriesWithContext(mock.Anything, &codecommit.ListRepositoriesInput{}).
|
||||
codeCommitClient.EXPECT().ListRepositories(mock.Anything, &codecommit.ListRepositoriesInput{}).
|
||||
Return(&codecommit.ListRepositoriesOutput{
|
||||
Repositories: codecommitRepoNameIdPairs,
|
||||
}, testCase.listRepositoryError).Maybe()
|
||||
} else {
|
||||
taggingClient.EXPECT().GetResourcesWithContext(mock.Anything, mock.MatchedBy(equalIgnoringTagFilterOrder(&resourcegroupstaggingapi.GetResourcesInput{
|
||||
taggingClient.EXPECT().GetResources(mock.Anything, mock.MatchedBy(equalIgnoringTagFilterOrder(&resourcegroupstaggingapi.GetResourcesInput{
|
||||
TagFilters: testCase.expectTagFilters,
|
||||
ResourceTypeFilters: aws.StringSlice([]string{resourceTypeCodeCommitRepository}),
|
||||
ResourceTypeFilters: []string{resourceTypeCodeCommitRepository},
|
||||
}))).
|
||||
Return(&resourcegroupstaggingapi.GetResourcesOutput{
|
||||
ResourceTagMappingList: resourceTaggings,
|
||||
|
|
@ -249,7 +252,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
path: "lib/config.yaml",
|
||||
expectedGetFolderPath: "/lib",
|
||||
getFolderOutput: &codecommit.GetFolderOutput{
|
||||
Files: []*codecommit.File{
|
||||
Files: []codecommittypes.File{
|
||||
{RelativePath: aws.String("config.yaml")},
|
||||
},
|
||||
},
|
||||
|
|
@ -261,7 +264,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
path: "lib/config",
|
||||
expectedGetFolderPath: "/lib",
|
||||
getFolderOutput: &codecommit.GetFolderOutput{
|
||||
SubFolders: []*codecommit.Folder{
|
||||
SubFolders: []codecommittypes.Folder{
|
||||
{RelativePath: aws.String("config")},
|
||||
},
|
||||
},
|
||||
|
|
@ -273,7 +276,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
path: "/lib/submodule/",
|
||||
expectedGetFolderPath: "/lib",
|
||||
getFolderOutput: &codecommit.GetFolderOutput{
|
||||
SubModules: []*codecommit.SubModule{
|
||||
SubModules: []codecommittypes.SubModule{
|
||||
{RelativePath: aws.String("submodule")},
|
||||
},
|
||||
},
|
||||
|
|
@ -285,7 +288,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
path: "./lib/service.json",
|
||||
expectedGetFolderPath: "/lib",
|
||||
getFolderOutput: &codecommit.GetFolderOutput{
|
||||
SymbolicLinks: []*codecommit.SymbolicLink{
|
||||
SymbolicLinks: []codecommittypes.SymbolicLink{
|
||||
{RelativePath: aws.String("service.json")},
|
||||
},
|
||||
},
|
||||
|
|
@ -297,16 +300,16 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
path: "no-match.json",
|
||||
expectedGetFolderPath: "/",
|
||||
getFolderOutput: &codecommit.GetFolderOutput{
|
||||
Files: []*codecommit.File{
|
||||
Files: []codecommittypes.File{
|
||||
{RelativePath: aws.String("config.yaml")},
|
||||
},
|
||||
SubFolders: []*codecommit.Folder{
|
||||
SubFolders: []codecommittypes.Folder{
|
||||
{RelativePath: aws.String("config")},
|
||||
},
|
||||
SubModules: []*codecommit.SubModule{
|
||||
SubModules: []codecommittypes.SubModule{
|
||||
{RelativePath: aws.String("submodule")},
|
||||
},
|
||||
SymbolicLinks: []*codecommit.SymbolicLink{
|
||||
SymbolicLinks: []codecommittypes.SymbolicLink{
|
||||
{RelativePath: aws.String("service.json")},
|
||||
},
|
||||
},
|
||||
|
|
@ -317,7 +320,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
name: "RepoHasPath when parent folder not found",
|
||||
path: "lib/submodule",
|
||||
expectedGetFolderPath: "/lib",
|
||||
getFolderError: &codecommit.FolderDoesNotExistException{},
|
||||
getFolderError: &codecommittypes.FolderDoesNotExistException{},
|
||||
expectOverallError: false,
|
||||
},
|
||||
{
|
||||
|
|
@ -347,7 +350,7 @@ func TestAWSCodeCommitRepoHasPath(t *testing.T) {
|
|||
taggingClient := mocks.NewAWSTaggingClient(t)
|
||||
ctx := t.Context()
|
||||
if testCase.expectedGetFolderPath != "" {
|
||||
codeCommitClient.EXPECT().GetFolderWithContext(mock.Anything, &codecommit.GetFolderInput{
|
||||
codeCommitClient.EXPECT().GetFolder(mock.Anything, &codecommit.GetFolderInput{
|
||||
CommitSpecifier: aws.String(branch),
|
||||
FolderPath: aws.String(testCase.expectedGetFolderPath),
|
||||
RepositoryName: aws.String(repoName),
|
||||
|
|
@ -419,13 +422,15 @@ func TestAWSCodeCommitGetBranches(t *testing.T) {
|
|||
taggingClient := mocks.NewAWSTaggingClient(t)
|
||||
ctx := t.Context()
|
||||
if testCase.allBranches {
|
||||
codeCommitClient.EXPECT().ListBranchesWithContext(mock.Anything, &codecommit.ListBranchesInput{
|
||||
branches := make([]string, len(testCase.branches))
|
||||
copy(branches, testCase.branches)
|
||||
codeCommitClient.EXPECT().ListBranches(mock.Anything, &codecommit.ListBranchesInput{
|
||||
RepositoryName: aws.String(name),
|
||||
}).
|
||||
Return(&codecommit.ListBranchesOutput{Branches: aws.StringSlice(testCase.branches)}, testCase.apiError).Maybe()
|
||||
Return(&codecommit.ListBranchesOutput{Branches: branches}, testCase.apiError).Maybe()
|
||||
} else {
|
||||
codeCommitClient.EXPECT().GetRepositoryWithContext(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(name)}).
|
||||
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: &codecommit.RepositoryMetadata{
|
||||
codeCommitClient.EXPECT().GetRepository(mock.Anything, &codecommit.GetRepositoryInput{RepositoryName: aws.String(name)}).
|
||||
Return(&codecommit.GetRepositoryOutput{RepositoryMetadata: &codecommittypes.RepositoryMetadata{
|
||||
AccountId: aws.String(organization),
|
||||
DefaultBranch: aws.String(defaultBranch),
|
||||
}}, testCase.apiError).Maybe()
|
||||
|
|
@ -470,8 +475,22 @@ func TestAWSCodeCommitGetBranches(t *testing.T) {
|
|||
func equalIgnoringTagFilterOrder(expected *resourcegroupstaggingapi.GetResourcesInput) func(*resourcegroupstaggingapi.GetResourcesInput) bool {
|
||||
return func(actual *resourcegroupstaggingapi.GetResourcesInput) bool {
|
||||
sort.Slice(actual.TagFilters, func(i, j int) bool {
|
||||
return *actual.TagFilters[i].Key < *actual.TagFilters[j].Key
|
||||
keyI := ""
|
||||
keyJ := ""
|
||||
if actual.TagFilters[i].Key != nil {
|
||||
keyI = *actual.TagFilters[i].Key
|
||||
}
|
||||
if actual.TagFilters[j].Key != nil {
|
||||
keyJ = *actual.TagFilters[j].Key
|
||||
}
|
||||
return keyI < keyJ
|
||||
})
|
||||
return cmp.Equal(expected, actual)
|
||||
// Ignore unexported fields in AWS SDK v2 types
|
||||
return cmp.Equal(expected, actual,
|
||||
cmpopts.IgnoreUnexported(
|
||||
rgsatypes.TagFilter{},
|
||||
resourcegroupstaggingapi.GetResourcesInput{},
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/service/codecommit"
|
||||
"context"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/codecommit"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
|
@ -38,71 +38,71 @@ func (_m *AWSCodeCommitClient) EXPECT() *AWSCodeCommitClient_Expecter {
|
|||
return &AWSCodeCommitClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetFolderWithContext provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) GetFolderWithContext(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option) (*codecommit.GetFolderOutput, error) {
|
||||
// request.Option
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
// GetFolder provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) GetFolder(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error) {
|
||||
// func(*codecommit.Options)
|
||||
_va := make([]interface{}, len(fns))
|
||||
for _i := range fns {
|
||||
_va[_i] = fns[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, v, getFolderInput)
|
||||
_ca = append(_ca, context1, getFolderInput)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _mock.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetFolderWithContext")
|
||||
panic("no return value specified for GetFolder")
|
||||
}
|
||||
|
||||
var r0 *codecommit.GetFolderOutput
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) (*codecommit.GetFolderOutput, error)); ok {
|
||||
return returnFunc(v, getFolderInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)); ok {
|
||||
return returnFunc(context1, getFolderInput, fns...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) *codecommit.GetFolderOutput); ok {
|
||||
r0 = returnFunc(v, getFolderInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) *codecommit.GetFolderOutput); ok {
|
||||
r0 = returnFunc(context1, getFolderInput, fns...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*codecommit.GetFolderOutput)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.GetFolderInput, ...request.Option) error); ok {
|
||||
r1 = returnFunc(v, getFolderInput, options...)
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.GetFolderInput, ...func(*codecommit.Options)) error); ok {
|
||||
r1 = returnFunc(context1, getFolderInput, fns...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AWSCodeCommitClient_GetFolderWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFolderWithContext'
|
||||
type AWSCodeCommitClient_GetFolderWithContext_Call struct {
|
||||
// AWSCodeCommitClient_GetFolder_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFolder'
|
||||
type AWSCodeCommitClient_GetFolder_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetFolderWithContext is a helper method to define mock.On call
|
||||
// - v aws.Context
|
||||
// GetFolder is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - getFolderInput *codecommit.GetFolderInput
|
||||
// - options ...request.Option
|
||||
func (_e *AWSCodeCommitClient_Expecter) GetFolderWithContext(v interface{}, getFolderInput interface{}, options ...interface{}) *AWSCodeCommitClient_GetFolderWithContext_Call {
|
||||
return &AWSCodeCommitClient_GetFolderWithContext_Call{Call: _e.mock.On("GetFolderWithContext",
|
||||
append([]interface{}{v, getFolderInput}, options...)...)}
|
||||
// - fns ...func(*codecommit.Options)
|
||||
func (_e *AWSCodeCommitClient_Expecter) GetFolder(context1 interface{}, getFolderInput interface{}, fns ...interface{}) *AWSCodeCommitClient_GetFolder_Call {
|
||||
return &AWSCodeCommitClient_GetFolder_Call{Call: _e.mock.On("GetFolder",
|
||||
append([]interface{}{context1, getFolderInput}, fns...)...)}
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Run(run func(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option)) *AWSCodeCommitClient_GetFolderWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetFolder_Call) Run(run func(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_GetFolder_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 aws.Context
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(aws.Context)
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *codecommit.GetFolderInput
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*codecommit.GetFolderInput)
|
||||
}
|
||||
var arg2 []request.Option
|
||||
variadicArgs := make([]request.Option, len(args)-2)
|
||||
var arg2 []func(*codecommit.Options)
|
||||
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(request.Option)
|
||||
variadicArgs[i] = a.(func(*codecommit.Options))
|
||||
}
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
|
|
@ -115,81 +115,81 @@ func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Run(run func(v aws.Cont
|
|||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) Return(getFolderOutput *codecommit.GetFolderOutput, err error) *AWSCodeCommitClient_GetFolderWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetFolder_Call) Return(getFolderOutput *codecommit.GetFolderOutput, err error) *AWSCodeCommitClient_GetFolder_Call {
|
||||
_c.Call.Return(getFolderOutput, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetFolderWithContext_Call) RunAndReturn(run func(v aws.Context, getFolderInput *codecommit.GetFolderInput, options ...request.Option) (*codecommit.GetFolderOutput, error)) *AWSCodeCommitClient_GetFolderWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetFolder_Call) RunAndReturn(run func(context1 context.Context, getFolderInput *codecommit.GetFolderInput, fns ...func(*codecommit.Options)) (*codecommit.GetFolderOutput, error)) *AWSCodeCommitClient_GetFolder_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetRepositoryWithContext provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) GetRepositoryWithContext(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option) (*codecommit.GetRepositoryOutput, error) {
|
||||
// request.Option
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
// GetRepository provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) GetRepository(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error) {
|
||||
// func(*codecommit.Options)
|
||||
_va := make([]interface{}, len(fns))
|
||||
for _i := range fns {
|
||||
_va[_i] = fns[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, v, getRepositoryInput)
|
||||
_ca = append(_ca, context1, getRepositoryInput)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _mock.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetRepositoryWithContext")
|
||||
panic("no return value specified for GetRepository")
|
||||
}
|
||||
|
||||
var r0 *codecommit.GetRepositoryOutput
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) (*codecommit.GetRepositoryOutput, error)); ok {
|
||||
return returnFunc(v, getRepositoryInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)); ok {
|
||||
return returnFunc(context1, getRepositoryInput, fns...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) *codecommit.GetRepositoryOutput); ok {
|
||||
r0 = returnFunc(v, getRepositoryInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) *codecommit.GetRepositoryOutput); ok {
|
||||
r0 = returnFunc(context1, getRepositoryInput, fns...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*codecommit.GetRepositoryOutput)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.GetRepositoryInput, ...request.Option) error); ok {
|
||||
r1 = returnFunc(v, getRepositoryInput, options...)
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.GetRepositoryInput, ...func(*codecommit.Options)) error); ok {
|
||||
r1 = returnFunc(context1, getRepositoryInput, fns...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AWSCodeCommitClient_GetRepositoryWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepositoryWithContext'
|
||||
type AWSCodeCommitClient_GetRepositoryWithContext_Call struct {
|
||||
// AWSCodeCommitClient_GetRepository_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetRepository'
|
||||
type AWSCodeCommitClient_GetRepository_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetRepositoryWithContext is a helper method to define mock.On call
|
||||
// - v aws.Context
|
||||
// GetRepository is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - getRepositoryInput *codecommit.GetRepositoryInput
|
||||
// - options ...request.Option
|
||||
func (_e *AWSCodeCommitClient_Expecter) GetRepositoryWithContext(v interface{}, getRepositoryInput interface{}, options ...interface{}) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
|
||||
return &AWSCodeCommitClient_GetRepositoryWithContext_Call{Call: _e.mock.On("GetRepositoryWithContext",
|
||||
append([]interface{}{v, getRepositoryInput}, options...)...)}
|
||||
// - fns ...func(*codecommit.Options)
|
||||
func (_e *AWSCodeCommitClient_Expecter) GetRepository(context1 interface{}, getRepositoryInput interface{}, fns ...interface{}) *AWSCodeCommitClient_GetRepository_Call {
|
||||
return &AWSCodeCommitClient_GetRepository_Call{Call: _e.mock.On("GetRepository",
|
||||
append([]interface{}{context1, getRepositoryInput}, fns...)...)}
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Run(run func(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option)) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetRepository_Call) Run(run func(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_GetRepository_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 aws.Context
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(aws.Context)
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *codecommit.GetRepositoryInput
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*codecommit.GetRepositoryInput)
|
||||
}
|
||||
var arg2 []request.Option
|
||||
variadicArgs := make([]request.Option, len(args)-2)
|
||||
var arg2 []func(*codecommit.Options)
|
||||
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(request.Option)
|
||||
variadicArgs[i] = a.(func(*codecommit.Options))
|
||||
}
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
|
|
@ -202,81 +202,81 @@ func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Run(run func(v aws.
|
|||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) Return(getRepositoryOutput *codecommit.GetRepositoryOutput, err error) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetRepository_Call) Return(getRepositoryOutput *codecommit.GetRepositoryOutput, err error) *AWSCodeCommitClient_GetRepository_Call {
|
||||
_c.Call.Return(getRepositoryOutput, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_GetRepositoryWithContext_Call) RunAndReturn(run func(v aws.Context, getRepositoryInput *codecommit.GetRepositoryInput, options ...request.Option) (*codecommit.GetRepositoryOutput, error)) *AWSCodeCommitClient_GetRepositoryWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_GetRepository_Call) RunAndReturn(run func(context1 context.Context, getRepositoryInput *codecommit.GetRepositoryInput, fns ...func(*codecommit.Options)) (*codecommit.GetRepositoryOutput, error)) *AWSCodeCommitClient_GetRepository_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListBranchesWithContext provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) ListBranchesWithContext(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option) (*codecommit.ListBranchesOutput, error) {
|
||||
// request.Option
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
// ListBranches provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) ListBranches(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error) {
|
||||
// func(*codecommit.Options)
|
||||
_va := make([]interface{}, len(fns))
|
||||
for _i := range fns {
|
||||
_va[_i] = fns[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, v, listBranchesInput)
|
||||
_ca = append(_ca, context1, listBranchesInput)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _mock.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListBranchesWithContext")
|
||||
panic("no return value specified for ListBranches")
|
||||
}
|
||||
|
||||
var r0 *codecommit.ListBranchesOutput
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) (*codecommit.ListBranchesOutput, error)); ok {
|
||||
return returnFunc(v, listBranchesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)); ok {
|
||||
return returnFunc(context1, listBranchesInput, fns...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) *codecommit.ListBranchesOutput); ok {
|
||||
r0 = returnFunc(v, listBranchesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) *codecommit.ListBranchesOutput); ok {
|
||||
r0 = returnFunc(context1, listBranchesInput, fns...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*codecommit.ListBranchesOutput)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.ListBranchesInput, ...request.Option) error); ok {
|
||||
r1 = returnFunc(v, listBranchesInput, options...)
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.ListBranchesInput, ...func(*codecommit.Options)) error); ok {
|
||||
r1 = returnFunc(context1, listBranchesInput, fns...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AWSCodeCommitClient_ListBranchesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBranchesWithContext'
|
||||
type AWSCodeCommitClient_ListBranchesWithContext_Call struct {
|
||||
// AWSCodeCommitClient_ListBranches_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListBranches'
|
||||
type AWSCodeCommitClient_ListBranches_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListBranchesWithContext is a helper method to define mock.On call
|
||||
// - v aws.Context
|
||||
// ListBranches is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - listBranchesInput *codecommit.ListBranchesInput
|
||||
// - options ...request.Option
|
||||
func (_e *AWSCodeCommitClient_Expecter) ListBranchesWithContext(v interface{}, listBranchesInput interface{}, options ...interface{}) *AWSCodeCommitClient_ListBranchesWithContext_Call {
|
||||
return &AWSCodeCommitClient_ListBranchesWithContext_Call{Call: _e.mock.On("ListBranchesWithContext",
|
||||
append([]interface{}{v, listBranchesInput}, options...)...)}
|
||||
// - fns ...func(*codecommit.Options)
|
||||
func (_e *AWSCodeCommitClient_Expecter) ListBranches(context1 interface{}, listBranchesInput interface{}, fns ...interface{}) *AWSCodeCommitClient_ListBranches_Call {
|
||||
return &AWSCodeCommitClient_ListBranches_Call{Call: _e.mock.On("ListBranches",
|
||||
append([]interface{}{context1, listBranchesInput}, fns...)...)}
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Run(run func(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option)) *AWSCodeCommitClient_ListBranchesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListBranches_Call) Run(run func(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_ListBranches_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 aws.Context
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(aws.Context)
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *codecommit.ListBranchesInput
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*codecommit.ListBranchesInput)
|
||||
}
|
||||
var arg2 []request.Option
|
||||
variadicArgs := make([]request.Option, len(args)-2)
|
||||
var arg2 []func(*codecommit.Options)
|
||||
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(request.Option)
|
||||
variadicArgs[i] = a.(func(*codecommit.Options))
|
||||
}
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
|
|
@ -289,81 +289,81 @@ func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Run(run func(v aws.C
|
|||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) Return(listBranchesOutput *codecommit.ListBranchesOutput, err error) *AWSCodeCommitClient_ListBranchesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListBranches_Call) Return(listBranchesOutput *codecommit.ListBranchesOutput, err error) *AWSCodeCommitClient_ListBranches_Call {
|
||||
_c.Call.Return(listBranchesOutput, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListBranchesWithContext_Call) RunAndReturn(run func(v aws.Context, listBranchesInput *codecommit.ListBranchesInput, options ...request.Option) (*codecommit.ListBranchesOutput, error)) *AWSCodeCommitClient_ListBranchesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListBranches_Call) RunAndReturn(run func(context1 context.Context, listBranchesInput *codecommit.ListBranchesInput, fns ...func(*codecommit.Options)) (*codecommit.ListBranchesOutput, error)) *AWSCodeCommitClient_ListBranches_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListRepositoriesWithContext provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) ListRepositoriesWithContext(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option) (*codecommit.ListRepositoriesOutput, error) {
|
||||
// request.Option
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
// ListRepositories provides a mock function for the type AWSCodeCommitClient
|
||||
func (_mock *AWSCodeCommitClient) ListRepositories(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error) {
|
||||
// func(*codecommit.Options)
|
||||
_va := make([]interface{}, len(fns))
|
||||
for _i := range fns {
|
||||
_va[_i] = fns[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, v, listRepositoriesInput)
|
||||
_ca = append(_ca, context1, listRepositoriesInput)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _mock.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListRepositoriesWithContext")
|
||||
panic("no return value specified for ListRepositories")
|
||||
}
|
||||
|
||||
var r0 *codecommit.ListRepositoriesOutput
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) (*codecommit.ListRepositoriesOutput, error)); ok {
|
||||
return returnFunc(v, listRepositoriesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)); ok {
|
||||
return returnFunc(context1, listRepositoriesInput, fns...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) *codecommit.ListRepositoriesOutput); ok {
|
||||
r0 = returnFunc(v, listRepositoriesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) *codecommit.ListRepositoriesOutput); ok {
|
||||
r0 = returnFunc(context1, listRepositoriesInput, fns...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*codecommit.ListRepositoriesOutput)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(aws.Context, *codecommit.ListRepositoriesInput, ...request.Option) error); ok {
|
||||
r1 = returnFunc(v, listRepositoriesInput, options...)
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *codecommit.ListRepositoriesInput, ...func(*codecommit.Options)) error); ok {
|
||||
r1 = returnFunc(context1, listRepositoriesInput, fns...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AWSCodeCommitClient_ListRepositoriesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListRepositoriesWithContext'
|
||||
type AWSCodeCommitClient_ListRepositoriesWithContext_Call struct {
|
||||
// AWSCodeCommitClient_ListRepositories_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListRepositories'
|
||||
type AWSCodeCommitClient_ListRepositories_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListRepositoriesWithContext is a helper method to define mock.On call
|
||||
// - v aws.Context
|
||||
// ListRepositories is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - listRepositoriesInput *codecommit.ListRepositoriesInput
|
||||
// - options ...request.Option
|
||||
func (_e *AWSCodeCommitClient_Expecter) ListRepositoriesWithContext(v interface{}, listRepositoriesInput interface{}, options ...interface{}) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
|
||||
return &AWSCodeCommitClient_ListRepositoriesWithContext_Call{Call: _e.mock.On("ListRepositoriesWithContext",
|
||||
append([]interface{}{v, listRepositoriesInput}, options...)...)}
|
||||
// - fns ...func(*codecommit.Options)
|
||||
func (_e *AWSCodeCommitClient_Expecter) ListRepositories(context1 interface{}, listRepositoriesInput interface{}, fns ...interface{}) *AWSCodeCommitClient_ListRepositories_Call {
|
||||
return &AWSCodeCommitClient_ListRepositories_Call{Call: _e.mock.On("ListRepositories",
|
||||
append([]interface{}{context1, listRepositoriesInput}, fns...)...)}
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Run(run func(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option)) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListRepositories_Call) Run(run func(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options))) *AWSCodeCommitClient_ListRepositories_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 aws.Context
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(aws.Context)
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *codecommit.ListRepositoriesInput
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*codecommit.ListRepositoriesInput)
|
||||
}
|
||||
var arg2 []request.Option
|
||||
variadicArgs := make([]request.Option, len(args)-2)
|
||||
var arg2 []func(*codecommit.Options)
|
||||
variadicArgs := make([]func(*codecommit.Options), len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(request.Option)
|
||||
variadicArgs[i] = a.(func(*codecommit.Options))
|
||||
}
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
|
|
@ -376,12 +376,12 @@ func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Run(run func(v a
|
|||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) Return(listRepositoriesOutput *codecommit.ListRepositoriesOutput, err error) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListRepositories_Call) Return(listRepositoriesOutput *codecommit.ListRepositoriesOutput, err error) *AWSCodeCommitClient_ListRepositories_Call {
|
||||
_c.Call.Return(listRepositoriesOutput, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSCodeCommitClient_ListRepositoriesWithContext_Call) RunAndReturn(run func(v aws.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, options ...request.Option) (*codecommit.ListRepositoriesOutput, error)) *AWSCodeCommitClient_ListRepositoriesWithContext_Call {
|
||||
func (_c *AWSCodeCommitClient_ListRepositories_Call) RunAndReturn(run func(context1 context.Context, listRepositoriesInput *codecommit.ListRepositoriesInput, fns ...func(*codecommit.Options)) (*codecommit.ListRepositoriesOutput, error)) *AWSCodeCommitClient_ListRepositories_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
package mocks
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
|
||||
"context"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
|
@ -38,71 +38,71 @@ func (_m *AWSTaggingClient) EXPECT() *AWSTaggingClient_Expecter {
|
|||
return &AWSTaggingClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// GetResourcesWithContext provides a mock function for the type AWSTaggingClient
|
||||
func (_mock *AWSTaggingClient) GetResourcesWithContext(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error) {
|
||||
// request.Option
|
||||
_va := make([]interface{}, len(options))
|
||||
for _i := range options {
|
||||
_va[_i] = options[_i]
|
||||
// GetResources provides a mock function for the type AWSTaggingClient
|
||||
func (_mock *AWSTaggingClient) GetResources(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error) {
|
||||
// func(*resourcegroupstaggingapi.Options)
|
||||
_va := make([]interface{}, len(fns))
|
||||
for _i := range fns {
|
||||
_va[_i] = fns[_i]
|
||||
}
|
||||
var _ca []interface{}
|
||||
_ca = append(_ca, v, getResourcesInput)
|
||||
_ca = append(_ca, context1, getResourcesInput)
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _mock.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetResourcesWithContext")
|
||||
panic("no return value specified for GetResources")
|
||||
}
|
||||
|
||||
var r0 *resourcegroupstaggingapi.GetResourcesOutput
|
||||
var r1 error
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)); ok {
|
||||
return returnFunc(v, getResourcesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)); ok {
|
||||
return returnFunc(context1, getResourcesInput, fns...)
|
||||
}
|
||||
if returnFunc, ok := ret.Get(0).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) *resourcegroupstaggingapi.GetResourcesOutput); ok {
|
||||
r0 = returnFunc(v, getResourcesInput, options...)
|
||||
if returnFunc, ok := ret.Get(0).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) *resourcegroupstaggingapi.GetResourcesOutput); ok {
|
||||
r0 = returnFunc(context1, getResourcesInput, fns...)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*resourcegroupstaggingapi.GetResourcesOutput)
|
||||
}
|
||||
}
|
||||
if returnFunc, ok := ret.Get(1).(func(aws.Context, *resourcegroupstaggingapi.GetResourcesInput, ...request.Option) error); ok {
|
||||
r1 = returnFunc(v, getResourcesInput, options...)
|
||||
if returnFunc, ok := ret.Get(1).(func(context.Context, *resourcegroupstaggingapi.GetResourcesInput, ...func(*resourcegroupstaggingapi.Options)) error); ok {
|
||||
r1 = returnFunc(context1, getResourcesInput, fns...)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AWSTaggingClient_GetResourcesWithContext_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetResourcesWithContext'
|
||||
type AWSTaggingClient_GetResourcesWithContext_Call struct {
|
||||
// AWSTaggingClient_GetResources_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetResources'
|
||||
type AWSTaggingClient_GetResources_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetResourcesWithContext is a helper method to define mock.On call
|
||||
// - v aws.Context
|
||||
// GetResources is a helper method to define mock.On call
|
||||
// - context1 context.Context
|
||||
// - getResourcesInput *resourcegroupstaggingapi.GetResourcesInput
|
||||
// - options ...request.Option
|
||||
func (_e *AWSTaggingClient_Expecter) GetResourcesWithContext(v interface{}, getResourcesInput interface{}, options ...interface{}) *AWSTaggingClient_GetResourcesWithContext_Call {
|
||||
return &AWSTaggingClient_GetResourcesWithContext_Call{Call: _e.mock.On("GetResourcesWithContext",
|
||||
append([]interface{}{v, getResourcesInput}, options...)...)}
|
||||
// - fns ...func(*resourcegroupstaggingapi.Options)
|
||||
func (_e *AWSTaggingClient_Expecter) GetResources(context1 interface{}, getResourcesInput interface{}, fns ...interface{}) *AWSTaggingClient_GetResources_Call {
|
||||
return &AWSTaggingClient_GetResources_Call{Call: _e.mock.On("GetResources",
|
||||
append([]interface{}{context1, getResourcesInput}, fns...)...)}
|
||||
}
|
||||
|
||||
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Run(run func(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option)) *AWSTaggingClient_GetResourcesWithContext_Call {
|
||||
func (_c *AWSTaggingClient_GetResources_Call) Run(run func(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options))) *AWSTaggingClient_GetResources_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
var arg0 aws.Context
|
||||
var arg0 context.Context
|
||||
if args[0] != nil {
|
||||
arg0 = args[0].(aws.Context)
|
||||
arg0 = args[0].(context.Context)
|
||||
}
|
||||
var arg1 *resourcegroupstaggingapi.GetResourcesInput
|
||||
if args[1] != nil {
|
||||
arg1 = args[1].(*resourcegroupstaggingapi.GetResourcesInput)
|
||||
}
|
||||
var arg2 []request.Option
|
||||
variadicArgs := make([]request.Option, len(args)-2)
|
||||
var arg2 []func(*resourcegroupstaggingapi.Options)
|
||||
variadicArgs := make([]func(*resourcegroupstaggingapi.Options), len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(request.Option)
|
||||
variadicArgs[i] = a.(func(*resourcegroupstaggingapi.Options))
|
||||
}
|
||||
}
|
||||
arg2 = variadicArgs
|
||||
|
|
@ -115,12 +115,12 @@ func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Run(run func(v aws.Cont
|
|||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) Return(getResourcesOutput *resourcegroupstaggingapi.GetResourcesOutput, err error) *AWSTaggingClient_GetResourcesWithContext_Call {
|
||||
func (_c *AWSTaggingClient_GetResources_Call) Return(getResourcesOutput *resourcegroupstaggingapi.GetResourcesOutput, err error) *AWSTaggingClient_GetResources_Call {
|
||||
_c.Call.Return(getResourcesOutput, err)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *AWSTaggingClient_GetResourcesWithContext_Call) RunAndReturn(run func(v aws.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, options ...request.Option) (*resourcegroupstaggingapi.GetResourcesOutput, error)) *AWSTaggingClient_GetResourcesWithContext_Call {
|
||||
func (_c *AWSTaggingClient_GetResources_Call) RunAndReturn(run func(context1 context.Context, getResourcesInput *resourcegroupstaggingapi.GetResourcesInput, fns ...func(*resourcegroupstaggingapi.Options)) (*resourcegroupstaggingapi.GetResourcesOutput, error)) *AWSTaggingClient_GetResources_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package commands
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
|
@ -162,7 +163,7 @@ func NewCommand() *cobra.Command {
|
|||
},
|
||||
}
|
||||
clientConfig = cli.AddKubectlFlagsToCmd(&command)
|
||||
command.Flags().IntVar(&processorsCount, "processors-count", 1, "Processors count.")
|
||||
command.Flags().IntVar(&processorsCount, "processors-count", env.ParseNumFromEnv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", 1, 1, math.MaxInt32), "Processors count.")
|
||||
command.Flags().StringVar(&appLabelSelector, "app-label-selector", "", "App label selector.")
|
||||
command.Flags().StringVar(&logLevel, "loglevel", env.StringFromEnv("ARGOCD_NOTIFICATIONS_CONTROLLER_LOGLEVEL", "info"), "Set the logging level. One of: debug|info|warn|error")
|
||||
command.Flags().StringVar(&logFormat, "logformat", env.StringFromEnv("ARGOCD_NOTIFICATIONS_CONTROLLER_LOGFORMAT", "json"), "Set the logging format. One of: json|text")
|
||||
|
|
|
|||
28
cmd/argocd-notification/commands/argocd_notification_test.go
Normal file
28
cmd/argocd-notification/commands/argocd_notification_test.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestNewCommandProcessorsCountDefault(t *testing.T) {
|
||||
t.Setenv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", "4")
|
||||
|
||||
cmd := NewCommand()
|
||||
|
||||
processorsCount, err := cmd.Flags().GetInt("processors-count")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 4, processorsCount)
|
||||
}
|
||||
|
||||
func TestNewCommandProcessorsCountInvalidEnvFallsBackToDefault(t *testing.T) {
|
||||
t.Setenv("ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT", "0")
|
||||
|
||||
cmd := NewCommand()
|
||||
|
||||
processorsCount, err := cmd.Flags().GetInt("processors-count")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, 1, processorsCount)
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
stderrors "errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
|
@ -62,6 +64,7 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
|||
fromFile string
|
||||
upsert bool
|
||||
)
|
||||
|
||||
command := &cobra.Command{
|
||||
Use: "add-tls SERVERNAME",
|
||||
Short: "Add TLS certificate data for connecting to repository server SERVERNAME",
|
||||
|
|
@ -76,8 +79,10 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
|||
os.Exit(1)
|
||||
}
|
||||
|
||||
var certificateArray []string
|
||||
var err error
|
||||
var (
|
||||
certificateArray []string
|
||||
err error
|
||||
)
|
||||
|
||||
if fromFile != "" {
|
||||
fmt.Printf("Reading TLS certificate data in PEM format from '%s'\n", fromFile)
|
||||
|
|
@ -86,49 +91,42 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
|||
fmt.Println("Enter TLS certificate data in PEM format. Press CTRL-D when finished.")
|
||||
certificateArray, err = certutil.ParseTLSCertificatesFromStream(os.Stdin)
|
||||
}
|
||||
|
||||
errors.CheckError(err)
|
||||
|
||||
certificateList := make([]appsv1.RepositoryCertificate, 0)
|
||||
uniqueCerts, err := deduplicatePEMCertificates(certificateArray)
|
||||
errors.CheckError(err)
|
||||
|
||||
subjectMap := make(map[string]*x509.Certificate)
|
||||
|
||||
for _, entry := range certificateArray {
|
||||
// We want to make sure to only send valid certificate data to the
|
||||
// server, so we decode the certificate into X509 structure before
|
||||
// further processing it.
|
||||
x509cert, err := certutil.DecodePEMCertificateToX509(entry)
|
||||
errors.CheckError(err)
|
||||
|
||||
// TODO: We need a better way to detect duplicates sent in the stream,
|
||||
// maybe by using fingerprints? For now, no two certs with the same
|
||||
// subject may be sent.
|
||||
if subjectMap[x509cert.Subject.String()] != nil {
|
||||
fmt.Printf("ERROR: Cert with subject '%s' already seen in the input stream.\n", x509cert.Subject.String())
|
||||
continue
|
||||
}
|
||||
subjectMap[x509cert.Subject.String()] = x509cert
|
||||
if len(uniqueCerts) == 0 {
|
||||
fmt.Println("No valid certificates have been detected in the stream.")
|
||||
return
|
||||
}
|
||||
|
||||
serverName := args[0]
|
||||
|
||||
if len(certificateArray) > 0 {
|
||||
certificateList = append(certificateList, appsv1.RepositoryCertificate{
|
||||
certificateList := []appsv1.RepositoryCertificate{
|
||||
{
|
||||
ServerName: serverName,
|
||||
CertType: "https",
|
||||
CertData: []byte(strings.Join(certificateArray, "\n")),
|
||||
})
|
||||
certificates, err := certIf.CreateCertificate(ctx, &certificatepkg.RepositoryCertificateCreateRequest{
|
||||
CertData: []byte(strings.Join(uniqueCerts, "\n")),
|
||||
},
|
||||
}
|
||||
|
||||
_, err = certIf.CreateCertificate(
|
||||
ctx,
|
||||
&certificatepkg.RepositoryCertificateCreateRequest{
|
||||
Certificates: &appsv1.RepositoryCertificateList{
|
||||
Items: certificateList,
|
||||
},
|
||||
Upsert: upsert,
|
||||
})
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Created entry with %d PEM certificates for repository server %s\n", len(certificates.Items), serverName)
|
||||
} else {
|
||||
fmt.Printf("No valid certificates have been detected in the stream.\n")
|
||||
}
|
||||
},
|
||||
)
|
||||
errors.CheckError(err)
|
||||
|
||||
fmt.Printf(
|
||||
"Created/updated TLS certificate entry for repository server %s with %d unique PEM certificates\n",
|
||||
serverName,
|
||||
len(uniqueCerts),
|
||||
)
|
||||
},
|
||||
}
|
||||
command.Flags().StringVar(&fromFile, "from", "", "Read TLS certificate data from file (default is to read from stdin)")
|
||||
|
|
@ -136,6 +134,45 @@ func NewCertAddTLSCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
|
|||
return command
|
||||
}
|
||||
|
||||
// certFingerprintSHA256 returns the SHA256 fingerprint of the given X.509 certificate.
|
||||
// The fingerprint is returned as a lowercase hexadecimal string.
|
||||
func certFingerprintSHA256(cert *x509.Certificate) string {
|
||||
sum := sha256.Sum256(cert.Raw)
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// deduplicatePEMCertificates removes duplicate PEM certificates from the input slice.
|
||||
// Two certificates are considered duplicates if their SHA256 fingerprints match.
|
||||
// The function returns a slice of unique certificates in the original order.
|
||||
// If any certificate cannot be decoded into X.509 format, an error is returned.
|
||||
func deduplicatePEMCertificates(pems []string) ([]string, error) {
|
||||
fingerprintMap := make(map[string]struct{})
|
||||
uniqueCerts := make([]string, 0)
|
||||
|
||||
for _, entry := range pems {
|
||||
x509cert, err := certutil.DecodePEMCertificateToX509(entry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fingerprint := certFingerprintSHA256(x509cert)
|
||||
|
||||
if _, exists := fingerprintMap[fingerprint]; exists {
|
||||
fmt.Printf(
|
||||
"WARNING: Duplicate certificate detected (SHA256 fingerprint %s, subject '%s'), skipping.\n",
|
||||
fingerprint,
|
||||
x509cert.Subject.String(),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
fingerprintMap[fingerprint] = struct{}{}
|
||||
uniqueCerts = append(uniqueCerts, entry)
|
||||
}
|
||||
|
||||
return uniqueCerts, nil
|
||||
}
|
||||
|
||||
// NewCertAddSSHCommand returns a new instance of an `argocd cert add` command
|
||||
func NewCertAddSSHCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
|
|
|
|||
108
cmd/argocd/commands/cert_test.go
Normal file
108
cmd/argocd/commands/cert_test.go
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func generateTestCert(t *testing.T, cn string) string {
|
||||
t.Helper()
|
||||
|
||||
priv, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
require.NoError(t, err)
|
||||
|
||||
template := &x509.Certificate{
|
||||
SerialNumber: big.NewInt(time.Now().UnixNano()),
|
||||
Subject: pkix.Name{
|
||||
CommonName: cn,
|
||||
},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour),
|
||||
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||
}
|
||||
|
||||
der, err := x509.CreateCertificate(
|
||||
rand.Reader,
|
||||
template,
|
||||
template,
|
||||
&priv.PublicKey,
|
||||
priv,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
var buf bytes.Buffer
|
||||
require.NoError(t, pem.Encode(&buf, &pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Bytes: der,
|
||||
}))
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_DuplicateCerts(t *testing.T) {
|
||||
cert := generateTestCert(t, "repo.example.com")
|
||||
|
||||
pems := []string{cert, cert}
|
||||
|
||||
unique, err := deduplicatePEMCertificates(pems)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, unique, 1)
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_SameSubjectDifferentCerts(t *testing.T) {
|
||||
cert1 := generateTestCert(t, "repo.example.com")
|
||||
cert2 := generateTestCert(t, "repo.example.com")
|
||||
|
||||
pems := []string{cert1, cert2}
|
||||
|
||||
unique, err := deduplicatePEMCertificates(pems)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, unique, 2)
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_InvalidCert(t *testing.T) {
|
||||
pems := []string{"not a cert"}
|
||||
|
||||
_, err := deduplicatePEMCertificates(pems)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_EmptyInput(t *testing.T) {
|
||||
unique, err := deduplicatePEMCertificates([]string{})
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, unique)
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_LargeNumberOfCerts(t *testing.T) {
|
||||
const numCerts = 100
|
||||
pems := make([]string, numCerts)
|
||||
for i := range numCerts {
|
||||
pems[i] = generateTestCert(t, fmt.Sprintf("host%d.example.com", i))
|
||||
}
|
||||
unique, err := deduplicatePEMCertificates(pems)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, unique, numCerts)
|
||||
}
|
||||
|
||||
func TestDeduplicatePEMCertificates_MixedValidAndInvalid(t *testing.T) {
|
||||
cert1 := generateTestCert(t, "valid1.example.com")
|
||||
cert2 := generateTestCert(t, "valid2.example.com")
|
||||
// invalid entry before the valid ones — deduplicatePEMCertificates stops at first error
|
||||
pems := []string{"not a cert", cert1, cert2}
|
||||
_, err := deduplicatePEMCertificates(pems)
|
||||
require.Error(t, err)
|
||||
// invalid entry after some valid ones — same behaviour
|
||||
pems = []string{cert1, "not a cert", cert2}
|
||||
_, err = deduplicatePEMCertificates(pems)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ import (
|
|||
)
|
||||
|
||||
// NewConfigureCommand returns a new instance of an `argocd configure` command
|
||||
func NewConfigureCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
func NewConfigureCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var promptsEnabled bool
|
||||
|
||||
command := &cobra.Command{
|
||||
|
|
@ -26,7 +26,7 @@ argocd configure --prompts-enabled=true
|
|||
# Disable optional interactive prompts
|
||||
argocd configure --prompts-enabled=false`,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
localCfg, err := localconfig.ReadLocalConfig(globalClientOpts.ConfigPath)
|
||||
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
if localCfg == nil {
|
||||
fmt.Println("No local configuration found")
|
||||
|
|
@ -35,7 +35,7 @@ argocd configure --prompts-enabled=false`,
|
|||
|
||||
localCfg.PromptsEnabled = promptsEnabled
|
||||
|
||||
err = localconfig.WriteLocalConfig(*localCfg, globalClientOpts.ConfigPath)
|
||||
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
|
||||
fmt.Println("Successfully updated the following configuration settings:")
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import (
|
|||
)
|
||||
|
||||
// NewLoginCommand returns a new instance of `argocd login` command
|
||||
func NewLoginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
func NewLoginCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
ctxName string
|
||||
username string
|
||||
|
|
@ -64,15 +64,15 @@ argocd login cd.argoproj.io --core`,
|
|||
|
||||
var server string
|
||||
|
||||
if len(args) != 1 && !globalClientOpts.PortForward && !globalClientOpts.Core {
|
||||
if len(args) != 1 && !clientOpts.PortForward && !clientOpts.Core {
|
||||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
switch {
|
||||
case globalClientOpts.PortForward:
|
||||
case clientOpts.PortForward:
|
||||
server = "port-forward"
|
||||
case globalClientOpts.Core:
|
||||
case clientOpts.Core:
|
||||
server = "kubernetes"
|
||||
default:
|
||||
server = args[0]
|
||||
|
|
@ -82,42 +82,42 @@ argocd login cd.argoproj.io --core`,
|
|||
tlsTestResult, err := grpc_util.TestTLS(server, dialTime)
|
||||
errors.CheckError(err)
|
||||
if !tlsTestResult.TLS {
|
||||
if !globalClientOpts.PlainText {
|
||||
if !clientOpts.PlainText {
|
||||
if !cli.AskToProceed("WARNING: server is not configured with TLS. Proceed (y/n)? ") {
|
||||
os.Exit(1)
|
||||
}
|
||||
globalClientOpts.PlainText = true
|
||||
clientOpts.PlainText = true
|
||||
}
|
||||
} else if tlsTestResult.InsecureErr != nil {
|
||||
if !globalClientOpts.Insecure {
|
||||
if !clientOpts.Insecure {
|
||||
if !cli.AskToProceed(fmt.Sprintf("WARNING: server certificate had error: %s. Proceed insecurely (y/n)? ", tlsTestResult.InsecureErr)) {
|
||||
os.Exit(1)
|
||||
}
|
||||
globalClientOpts.Insecure = true
|
||||
clientOpts.Insecure = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clientOpts := argocdclient.ClientOptions{
|
||||
loginOpts := argocdclient.ClientOptions{
|
||||
ConfigPath: "",
|
||||
ServerAddr: server,
|
||||
Insecure: globalClientOpts.Insecure,
|
||||
PlainText: globalClientOpts.PlainText,
|
||||
ClientCertFile: globalClientOpts.ClientCertFile,
|
||||
ClientCertKeyFile: globalClientOpts.ClientCertKeyFile,
|
||||
GRPCWeb: globalClientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
|
||||
PortForward: globalClientOpts.PortForward,
|
||||
PortForwardNamespace: globalClientOpts.PortForwardNamespace,
|
||||
Headers: globalClientOpts.Headers,
|
||||
KubeOverrides: globalClientOpts.KubeOverrides,
|
||||
ServerName: globalClientOpts.ServerName,
|
||||
Insecure: clientOpts.Insecure,
|
||||
PlainText: clientOpts.PlainText,
|
||||
ClientCertFile: clientOpts.ClientCertFile,
|
||||
ClientCertKeyFile: clientOpts.ClientCertKeyFile,
|
||||
GRPCWeb: clientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: clientOpts.GRPCWebRootPath,
|
||||
PortForward: clientOpts.PortForward,
|
||||
PortForwardNamespace: clientOpts.PortForwardNamespace,
|
||||
Headers: clientOpts.Headers,
|
||||
KubeOverrides: clientOpts.KubeOverrides,
|
||||
ServerName: clientOpts.ServerName,
|
||||
}
|
||||
|
||||
if ctxName == "" {
|
||||
ctxName = server
|
||||
if globalClientOpts.GRPCWebRootPath != "" {
|
||||
rootPath := strings.TrimRight(strings.TrimLeft(globalClientOpts.GRPCWebRootPath, "/"), "/")
|
||||
if loginOpts.GRPCWebRootPath != "" {
|
||||
rootPath := strings.TrimRight(strings.TrimLeft(loginOpts.GRPCWebRootPath, "/"), "/")
|
||||
ctxName = fmt.Sprintf("%s/%s", server, rootPath)
|
||||
}
|
||||
}
|
||||
|
|
@ -125,8 +125,8 @@ argocd login cd.argoproj.io --core`,
|
|||
// Perform the login
|
||||
var tokenString string
|
||||
var refreshToken string
|
||||
if !globalClientOpts.Core {
|
||||
acdClient := headless.NewClientOrDie(&clientOpts, c)
|
||||
if !clientOpts.Core {
|
||||
acdClient := headless.NewClientOrDie(&loginOpts, c)
|
||||
setConn, setIf := acdClient.NewSettingsClientOrDie()
|
||||
defer utilio.Close(setConn)
|
||||
if !sso {
|
||||
|
|
@ -149,18 +149,18 @@ argocd login cd.argoproj.io --core`,
|
|||
}
|
||||
|
||||
// login successful. Persist the config
|
||||
localCfg, err := localconfig.ReadLocalConfig(globalClientOpts.ConfigPath)
|
||||
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
if localCfg == nil {
|
||||
localCfg = &localconfig.LocalConfig{}
|
||||
}
|
||||
localCfg.UpsertServer(localconfig.Server{
|
||||
Server: server,
|
||||
PlainText: globalClientOpts.PlainText,
|
||||
Insecure: globalClientOpts.Insecure,
|
||||
GRPCWeb: globalClientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
|
||||
Core: globalClientOpts.Core,
|
||||
PlainText: clientOpts.PlainText,
|
||||
Insecure: clientOpts.Insecure,
|
||||
GRPCWeb: clientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: clientOpts.GRPCWebRootPath,
|
||||
Core: clientOpts.Core,
|
||||
})
|
||||
localCfg.UpsertUser(localconfig.User{
|
||||
Name: ctxName,
|
||||
|
|
@ -176,7 +176,7 @@ argocd login cd.argoproj.io --core`,
|
|||
User: ctxName,
|
||||
Server: server,
|
||||
})
|
||||
err = localconfig.WriteLocalConfig(*localCfg, globalClientOpts.ConfigPath)
|
||||
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Context '%s' updated\n", ctxName)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
)
|
||||
|
||||
// NewLogoutCommand returns a new instance of `argocd logout` command
|
||||
func NewLogoutCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
func NewLogoutCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
command := &cobra.Command{
|
||||
Use: "logout CONTEXT",
|
||||
Short: "Log out from Argo CD",
|
||||
|
|
@ -41,42 +41,42 @@ argocd logout cd.argoproj.io
|
|||
}
|
||||
context := args[0]
|
||||
|
||||
localCfg, err := localconfig.ReadLocalConfig(globalClientOpts.ConfigPath)
|
||||
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
|
||||
errutil.CheckError(err)
|
||||
if localCfg == nil {
|
||||
log.Fatalf("Nothing to logout from")
|
||||
}
|
||||
|
||||
promptUtil := utils.NewPrompt(globalClientOpts.PromptsEnabled)
|
||||
promptUtil := utils.NewPrompt(clientOpts.PromptsEnabled)
|
||||
|
||||
canLogout := promptUtil.Confirm(fmt.Sprintf("Are you sure you want to log out from '%s'?", context))
|
||||
if canLogout {
|
||||
if tlsTestResult, err := grpc_util.TestTLS(context, common.BearerTokenTimeout); err != nil {
|
||||
log.Warnf("failed to check the TLS config settings for the server : %v.", err)
|
||||
globalClientOpts.PlainText = true
|
||||
clientOpts.PlainText = true
|
||||
} else {
|
||||
if !tlsTestResult.TLS {
|
||||
if !globalClientOpts.PlainText {
|
||||
if !clientOpts.PlainText {
|
||||
if !cli.AskToProceed("WARNING: server is not configured with TLS. Proceed (y/n)? ") {
|
||||
os.Exit(1)
|
||||
}
|
||||
globalClientOpts.PlainText = true
|
||||
clientOpts.PlainText = true
|
||||
}
|
||||
} else if tlsTestResult.InsecureErr != nil {
|
||||
if !globalClientOpts.Insecure {
|
||||
if !clientOpts.Insecure {
|
||||
if !cli.AskToProceed(fmt.Sprintf("WARNING: server certificate had error: %s. Proceed insecurely (y/n)? ", tlsTestResult.InsecureErr)) {
|
||||
os.Exit(1)
|
||||
}
|
||||
globalClientOpts.Insecure = true
|
||||
clientOpts.Insecure = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scheme := "https"
|
||||
if globalClientOpts.PlainText {
|
||||
if clientOpts.PlainText {
|
||||
scheme = "http"
|
||||
}
|
||||
if res, err := revokeServerToken(scheme, context, localCfg.GetToken(context), globalClientOpts.Insecure); err != nil {
|
||||
if res, err := revokeServerToken(scheme, context, localCfg.GetToken(context), clientOpts.Insecure); err != nil {
|
||||
log.Warnf("failed to invalidate token on server: %v.", err)
|
||||
} else {
|
||||
_ = res.Body.Close()
|
||||
|
|
@ -97,7 +97,7 @@ argocd logout cd.argoproj.io
|
|||
if err != nil {
|
||||
log.Fatalf("Error in logging out: %s", err)
|
||||
}
|
||||
err = localconfig.WriteLocalConfig(*localCfg, globalClientOpts.ConfigPath)
|
||||
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
|
||||
errutil.CheckError(err)
|
||||
|
||||
fmt.Printf("Logged out from '%s'\n", context)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
)
|
||||
|
||||
// NewReloginCommand returns a new instance of `argocd relogin` command
|
||||
func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
func NewReloginCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
|
||||
var (
|
||||
password string
|
||||
callback string
|
||||
|
|
@ -37,7 +37,7 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm
|
|||
c.HelpFunc()(c, args)
|
||||
os.Exit(1)
|
||||
}
|
||||
localCfg, err := localconfig.ReadLocalConfig(globalClientOpts.ConfigPath)
|
||||
localCfg, err := localconfig.ReadLocalConfig(clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
if localCfg == nil {
|
||||
log.Fatalf("No context found. Login using `argocd login`")
|
||||
|
|
@ -47,18 +47,18 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm
|
|||
|
||||
var tokenString string
|
||||
var refreshToken string
|
||||
clientOpts := argocdclient.ClientOptions{
|
||||
reloginOpts := argocdclient.ClientOptions{
|
||||
ConfigPath: "",
|
||||
ServerAddr: configCtx.Server.Server,
|
||||
Insecure: configCtx.Server.Insecure,
|
||||
ClientCertFile: globalClientOpts.ClientCertFile,
|
||||
ClientCertKeyFile: globalClientOpts.ClientCertKeyFile,
|
||||
GRPCWeb: globalClientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: globalClientOpts.GRPCWebRootPath,
|
||||
ClientCertFile: clientOpts.ClientCertFile,
|
||||
ClientCertKeyFile: clientOpts.ClientCertKeyFile,
|
||||
GRPCWeb: clientOpts.GRPCWeb,
|
||||
GRPCWebRootPath: clientOpts.GRPCWebRootPath,
|
||||
PlainText: configCtx.Server.PlainText,
|
||||
Headers: globalClientOpts.Headers,
|
||||
Headers: clientOpts.Headers,
|
||||
}
|
||||
acdClient := headless.NewClientOrDie(&clientOpts, c)
|
||||
acdClient := headless.NewClientOrDie(&reloginOpts, c)
|
||||
claims, err := configCtx.User.Claims()
|
||||
errors.CheckError(err)
|
||||
if jwtutil.StringField(claims, "iss") == session.SessionManagerClaimsIssuer {
|
||||
|
|
@ -83,7 +83,7 @@ func NewReloginCommand(globalClientOpts *argocdclient.ClientOptions) *cobra.Comm
|
|||
AuthToken: tokenString,
|
||||
RefreshToken: refreshToken,
|
||||
})
|
||||
err = localconfig.WriteLocalConfig(*localCfg, globalClientOpts.ConfigPath)
|
||||
err = localconfig.WriteLocalConfig(*localCfg, clientOpts.ConfigPath)
|
||||
errors.CheckError(err)
|
||||
fmt.Printf("Context '%s' updated\n", localCfg.CurrentContext)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ import (
|
|||
)
|
||||
|
||||
func TestNewReloginCommand(t *testing.T) {
|
||||
globalClientOpts := argocdclient.ClientOptions{
|
||||
clientOpts := argocdclient.ClientOptions{
|
||||
ConfigPath: "/path/to/config",
|
||||
}
|
||||
|
||||
cmd := NewReloginCommand(&globalClientOpts)
|
||||
cmd := NewReloginCommand(&clientOpts)
|
||||
|
||||
assert.Equal(t, "relogin", cmd.Use, "Unexpected command Use")
|
||||
assert.Equal(t, "Refresh an expired authenticate token", cmd.Short, "Unexpected command Short")
|
||||
|
|
@ -33,8 +33,8 @@ func TestNewReloginCommand(t *testing.T) {
|
|||
assert.Equal(t, 8085, port, "Unexpected default value for --sso-port flag")
|
||||
}
|
||||
|
||||
func TestNewReloginCommandWithGlobalClientOptions(t *testing.T) {
|
||||
globalClientOpts := argocdclient.ClientOptions{
|
||||
func TestNewReloginCommandWithClientOptions(t *testing.T) {
|
||||
clientOpts := argocdclient.ClientOptions{
|
||||
ConfigPath: "/path/to/config",
|
||||
ServerAddr: "https://argocd-server.example.com",
|
||||
Insecure: true,
|
||||
|
|
@ -46,7 +46,7 @@ func TestNewReloginCommandWithGlobalClientOptions(t *testing.T) {
|
|||
Headers: []string{"header1", "header2"},
|
||||
}
|
||||
|
||||
cmd := NewReloginCommand(&globalClientOpts)
|
||||
cmd := NewReloginCommand(&clientOpts)
|
||||
|
||||
assert.Equal(t, "relogin", cmd.Use, "Unexpected command Use")
|
||||
assert.Equal(t, "Refresh an expired authenticate token", cmd.Short, "Unexpected command Short")
|
||||
|
|
|
|||
|
|
@ -393,6 +393,8 @@ data:
|
|||
notificationscontroller.log.level: "info"
|
||||
# Set the logging format. One of: json|text (default "json")
|
||||
notificationscontroller.log.format: "json"
|
||||
# Number of notification processors (default 1)
|
||||
notificationscontroller.processors.count: "1"
|
||||
# Enable self-service notifications config. Used in conjunction with apps-in-any-namespace. (default "false")
|
||||
notificationscontroller.selfservice.enabled: "false"
|
||||
# Disable TLS on connections to repo server
|
||||
|
|
|
|||
|
|
@ -70,6 +70,19 @@ data:
|
|||
notificationscontroller.selfservice.enabled: "true"
|
||||
```
|
||||
|
||||
Other notifications controller startup settings can be managed the same way. For notifications-heavy
|
||||
installations, `notificationscontroller.processors.count` configures the worker concurrency and maps
|
||||
to the `--processors-count` startup flag. For example:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: argocd-cmd-params-cm
|
||||
data:
|
||||
notificationscontroller.processors.count: "4"
|
||||
```
|
||||
|
||||
To use this feature, you can deploy configmap named `argocd-notifications-cm` and possibly a secret `argocd-notifications-secret` in the namespace where the Argo CD application lives.
|
||||
|
||||
When it is configured this way the controller will send notifications using both the controller level configuration (the configmap located in the same namespaces as the controller) as well as
|
||||
|
|
|
|||
|
|
@ -531,6 +531,22 @@ func (sc *syncContext) Sync() {
|
|||
multiStep := tasks.multiStep()
|
||||
runningTasks := tasks.Filter(func(t *syncTask) bool { return (multiStep || t.isHook()) && t.running() })
|
||||
if runningTasks.Len() > 0 {
|
||||
// check if any of the running task's resources are missing to prevent infinite loop of waiting for healthy
|
||||
for _, task := range runningTasks {
|
||||
if task.liveObj == nil {
|
||||
liveObj, err := sc.getResource(task)
|
||||
if err != nil && !apierrors.IsNotFound(err) {
|
||||
sc.setResourceResult(task, task.syncStatus, common.OperationError, fmt.Sprintf("Failed to get live resource %v", err))
|
||||
continue
|
||||
}
|
||||
if liveObj != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
sc.setResourceResult(task, common.ResultCodeSyncFailed, common.OperationError, fmt.Sprintf("Resource %s/%s/%s is missing, it might have been deleted", task.group(), task.kind(), task.name()))
|
||||
}
|
||||
}
|
||||
|
||||
sc.setRunningPhase(runningTasks, false)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,17 @@ func TestSyncNamespaceCreatedBeforeDryRunWithoutFailure(t *testing.T) {
|
|||
Live: []*unstructured.Unstructured{nil, nil},
|
||||
Target: []*unstructured.Unstructured{pod},
|
||||
})
|
||||
|
||||
ns := &unstructured.Unstructured{}
|
||||
ns.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"})
|
||||
ns.SetName(testingutils.FakeArgoCDNamespace)
|
||||
|
||||
fakeDynamicClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||
fakeDynamicClient.PrependReactor("get", "namespaces", func(action testcore.Action) (bool, runtime.Object, error) {
|
||||
return true, ns, nil
|
||||
})
|
||||
syncCtx.dynamicIf = fakeDynamicClient
|
||||
|
||||
syncCtx.Sync()
|
||||
phase, msg, resources := syncCtx.GetState()
|
||||
assert.Equal(t, synccommon.OperationRunning, phase)
|
||||
|
|
@ -348,6 +359,102 @@ func TestSyncSuccessfully_Multistep(t *testing.T) {
|
|||
assert.Len(t, resources, 2)
|
||||
}
|
||||
|
||||
func TestSync_MultistepResourceDeletionMidstep(t *testing.T) {
|
||||
pod1 := testingutils.NewPod()
|
||||
pod1.SetName("pod-1")
|
||||
pod1.SetNamespace("fake-argocd-ns")
|
||||
pod1.SetAnnotations(map[string]string{synccommon.AnnotationSyncWave: "1"})
|
||||
pod2 := testingutils.NewPod()
|
||||
pod2.SetName("pod-2")
|
||||
pod2.SetNamespace("fake-argocd-ns")
|
||||
pod2.SetAnnotations(map[string]string{synccommon.AnnotationSyncWave: "2"})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
resourcesStart map[kube.ResourceKey]reconciledResource
|
||||
resourcesChange map[kube.ResourceKey]reconciledResource
|
||||
statusExpected synccommon.ResultCode
|
||||
hookPhaseExpected synccommon.OperationPhase
|
||||
clientGet bool
|
||||
}{
|
||||
{
|
||||
name: "resource deleted during multistep",
|
||||
resourcesStart: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{pod1, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
resourcesChange: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{nil, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
statusExpected: synccommon.ResultCodeSyncFailed,
|
||||
hookPhaseExpected: synccommon.OperationError,
|
||||
clientGet: false,
|
||||
},
|
||||
{
|
||||
name: "no false positive on resource creation",
|
||||
resourcesStart: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{nil, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
resourcesChange: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{pod1, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
statusExpected: synccommon.ResultCodeSynced,
|
||||
hookPhaseExpected: synccommon.OperationRunning,
|
||||
clientGet: false,
|
||||
},
|
||||
{
|
||||
name: "resource created after task sync started",
|
||||
resourcesStart: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{nil, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
resourcesChange: groupResources(ReconciliationResult{
|
||||
Live: []*unstructured.Unstructured{nil, pod2},
|
||||
Target: []*unstructured.Unstructured{pod1, pod2},
|
||||
}),
|
||||
statusExpected: synccommon.ResultCodeSynced,
|
||||
hookPhaseExpected: synccommon.OperationRunning,
|
||||
clientGet: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
syncCtx := newTestSyncCtx(nil, WithResourceModificationChecker(true, diffResultList()))
|
||||
syncCtx.resources = tt.resourcesStart
|
||||
|
||||
fakeDynamicClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||
if tt.clientGet {
|
||||
fakeDynamicClient.PrependReactor("get", "pods", func(action testcore.Action) (bool, runtime.Object, error) {
|
||||
return true, pod1, nil
|
||||
})
|
||||
}
|
||||
syncCtx.dynamicIf = fakeDynamicClient
|
||||
|
||||
syncCtx.Sync()
|
||||
phase, _, resources := syncCtx.GetState()
|
||||
assert.Len(t, resources, 1)
|
||||
assert.Equal(t, "pod-1", resources[0].ResourceKey.Name)
|
||||
assert.Equal(t, synccommon.OperationRunning, phase)
|
||||
assert.Equal(t, synccommon.ResultCodeSynced, resources[0].Status)
|
||||
assert.Equal(t, synccommon.OperationRunning, resources[0].HookPhase)
|
||||
|
||||
syncCtx.resources = tt.resourcesChange
|
||||
|
||||
syncCtx.Sync()
|
||||
phase, _, resources = syncCtx.GetState()
|
||||
assert.Equal(t, synccommon.OperationRunning, phase)
|
||||
assert.Len(t, resources, 1)
|
||||
assert.Equal(t, "pod-1", resources[0].ResourceKey.Name)
|
||||
assert.Equal(t, tt.statusExpected, resources[0].Status)
|
||||
assert.Equal(t, tt.hookPhaseExpected, resources[0].HookPhase)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSyncDeleteSuccessfully(t *testing.T) {
|
||||
syncCtx := newTestSyncCtx(nil, WithOperationSettings(false, true, false, false))
|
||||
svc := testingutils.NewService()
|
||||
|
|
@ -514,6 +621,12 @@ func TestSync_ApplyOutOfSyncOnly(t *testing.T) {
|
|||
Target: []*unstructured.Unstructured{pod1, nil, pod3},
|
||||
})
|
||||
|
||||
fakeDynamicClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||
fakeDynamicClient.PrependReactor("get", "pods", func(action testcore.Action) (bool, runtime.Object, error) {
|
||||
return true, pod1, nil
|
||||
})
|
||||
syncCtx.dynamicIf = fakeDynamicClient
|
||||
|
||||
syncCtx.Sync()
|
||||
phase, _, resources := syncCtx.GetState()
|
||||
assert.Equal(t, synccommon.OperationRunning, phase)
|
||||
|
|
@ -1930,6 +2043,9 @@ func TestSync_SyncWaveHook(t *testing.T) {
|
|||
})
|
||||
syncCtx.hooks = []*unstructured.Unstructured{pod3}
|
||||
|
||||
fakeDynamicClient := fake.NewSimpleDynamicClient(runtime.NewScheme())
|
||||
syncCtx.dynamicIf = fakeDynamicClient
|
||||
|
||||
called := false
|
||||
syncCtx.syncWaveHook = func(phase synccommon.SyncPhase, wave int, final bool) error {
|
||||
called = true
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/cli-runtime/pkg/genericiooptions"
|
||||
"k8s.io/cli-runtime/pkg/printers"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"k8s.io/client-go/discovery"
|
||||
|
|
@ -65,7 +66,7 @@ type kubectlServerSideDiffDryRunApplier struct {
|
|||
openAPISchema openapi.Resources
|
||||
}
|
||||
|
||||
type commandExecutor func(ioStreams genericclioptions.IOStreams, fileName string) error
|
||||
type commandExecutor func(ioStreams genericiooptions.IOStreams, fileName string) error
|
||||
|
||||
func maybeLogManifest(manifestBytes []byte, log logr.Logger) error {
|
||||
// log manifest
|
||||
|
|
@ -111,7 +112,7 @@ func createManifestFile(obj *unstructured.Unstructured, log logr.Logger) (*os.Fi
|
|||
return manifestFile, nil
|
||||
}
|
||||
|
||||
func (k *kubectlResourceOperations) runResourceCommand(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, executor commandExecutor) (string, error) {
|
||||
func (k *kubectlResourceOperations) runResourceCommand(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, reconcileRBAC bool, executor commandExecutor) (string, error) {
|
||||
manifestFile, err := createManifestFile(obj, k.log)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -120,7 +121,7 @@ func (k *kubectlResourceOperations) runResourceCommand(ctx context.Context, obj
|
|||
|
||||
var out []string
|
||||
// rbac resources are first applied with auth reconcile kubectl feature.
|
||||
if obj.GetAPIVersion() == "rbac.authorization.k8s.io/v1" {
|
||||
if reconcileRBAC && obj.GetAPIVersion() == "rbac.authorization.k8s.io/v1" {
|
||||
outReconcile, err := k.rbacReconcile(ctx, obj, manifestFile.Name(), dryRunStrategy)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error running rbacReconcile: %w", err)
|
||||
|
|
@ -131,7 +132,7 @@ func (k *kubectlResourceOperations) runResourceCommand(ctx context.Context, obj
|
|||
}
|
||||
|
||||
// Run kubectl apply
|
||||
ioStreams := genericclioptions.IOStreams{
|
||||
ioStreams := genericiooptions.IOStreams{
|
||||
In: &bytes.Buffer{},
|
||||
Out: &bytes.Buffer{},
|
||||
ErrOut: &bytes.Buffer{},
|
||||
|
|
@ -160,7 +161,7 @@ func (k *kubectlServerSideDiffDryRunApplier) runResourceCommand(obj *unstructure
|
|||
stderrBuf := &bytes.Buffer{}
|
||||
|
||||
// Run kubectl apply
|
||||
ioStreams := genericclioptions.IOStreams{
|
||||
ioStreams := genericiooptions.IOStreams{
|
||||
In: &bytes.Buffer{},
|
||||
Out: stdoutBuf,
|
||||
ErrOut: stderrBuf,
|
||||
|
|
@ -226,7 +227,7 @@ func (k *kubectlResourceOperations) ReplaceResource(ctx context.Context, obj *un
|
|||
span.SetBaggageItem("name", obj.GetName())
|
||||
defer span.Finish()
|
||||
k.log.Info(fmt.Sprintf("Replacing resource %s/%s in cluster: %s, namespace: %s", obj.GetKind(), obj.GetName(), k.config.Host, obj.GetNamespace()))
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, func(ioStreams genericclioptions.IOStreams, fileName string) error {
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, false, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
cleanup, err := processKubectlRun(k.onKubectlRun, "replace")
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -248,7 +249,7 @@ func (k *kubectlResourceOperations) CreateResource(ctx context.Context, obj *uns
|
|||
span.SetBaggageItem("kind", gvk.Kind)
|
||||
span.SetBaggageItem("name", obj.GetName())
|
||||
defer span.Finish()
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, func(ioStreams genericclioptions.IOStreams, fileName string) error {
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, false, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
cleanup, err := processKubectlRun(k.onKubectlRun, "create")
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -313,7 +314,7 @@ func (k *kubectlServerSideDiffDryRunApplier) ApplyResource(_ context.Context, ob
|
|||
"manager", manager,
|
||||
"serverSideApply", serverSideApply).Info(fmt.Sprintf("Running server-side diff. Dry run applying resource %s/%s in cluster: %s, namespace: %s", obj.GetKind(), obj.GetName(), k.config.Host, obj.GetNamespace()))
|
||||
|
||||
return k.runResourceCommand(obj, func(ioStreams genericclioptions.IOStreams, fileName string) error {
|
||||
return k.runResourceCommand(obj, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
cleanup, err := processKubectlRun(k.onKubectlRun, "apply")
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -344,7 +345,7 @@ func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unst
|
|||
"serverSideApply", serverSideApply,
|
||||
"serverSideDiff", true).Info(fmt.Sprintf("Applying resource %s/%s in cluster: %s, namespace: %s", obj.GetKind(), obj.GetName(), k.config.Host, obj.GetNamespace()))
|
||||
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, func(ioStreams genericclioptions.IOStreams, fileName string) error {
|
||||
return k.runResourceCommand(ctx, obj, dryRunStrategy, true, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
cleanup, err := processKubectlRun(k.onKubectlRun, "apply")
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -359,7 +360,7 @@ func (k *kubectlResourceOperations) ApplyResource(ctx context.Context, obj *unst
|
|||
})
|
||||
}
|
||||
|
||||
func newApplyOptionsCommon(config *rest.Config, fact cmdutil.Factory, ioStreams genericclioptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
func newApplyOptionsCommon(config *rest.Config, fact cmdutil.Factory, ioStreams genericiooptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
flags := apply.NewApplyFlags(ioStreams)
|
||||
o := &apply.ApplyOptions{
|
||||
IOStreams: ioStreams,
|
||||
|
|
@ -407,7 +408,7 @@ func newApplyOptionsCommon(config *rest.Config, fact cmdutil.Factory, ioStreams
|
|||
return o, nil
|
||||
}
|
||||
|
||||
func (k *kubectlServerSideDiffDryRunApplier) newApplyOptions(ioStreams genericclioptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
func (k *kubectlServerSideDiffDryRunApplier) newApplyOptions(ioStreams genericiooptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
o, err := newApplyOptionsCommon(k.config, k.fact, ioStreams, obj, fileName, validate, force, serverSideApply, dryRunStrategy, manager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -436,7 +437,7 @@ func (k *kubectlServerSideDiffDryRunApplier) newApplyOptions(ioStreams genericcl
|
|||
return o, nil
|
||||
}
|
||||
|
||||
func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericclioptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericiooptions.IOStreams, obj *unstructured.Unstructured, fileName string, validate bool, force, serverSideApply bool, dryRunStrategy cmdutil.DryRunStrategy, manager string) (*apply.ApplyOptions, error) {
|
||||
o, err := newApplyOptionsCommon(k.config, k.fact, ioStreams, obj, fileName, validate, force, serverSideApply, dryRunStrategy, manager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -469,7 +470,7 @@ func (k *kubectlResourceOperations) newApplyOptions(ioStreams genericclioptions.
|
|||
return o, nil
|
||||
}
|
||||
|
||||
func (k *kubectlResourceOperations) newCreateOptions(ioStreams genericclioptions.IOStreams, fileName string, dryRunStrategy cmdutil.DryRunStrategy) (*create.CreateOptions, error) {
|
||||
func (k *kubectlResourceOperations) newCreateOptions(ioStreams genericiooptions.IOStreams, fileName string, dryRunStrategy cmdutil.DryRunStrategy) (*create.CreateOptions, error) {
|
||||
o := create.NewCreateOptions(ioStreams)
|
||||
|
||||
recorder, err := o.RecordFlags.ToRecorder()
|
||||
|
|
@ -507,7 +508,7 @@ func (k *kubectlResourceOperations) newCreateOptions(ioStreams genericclioptions
|
|||
return o, nil
|
||||
}
|
||||
|
||||
func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmdutil.Factory, ioStreams genericclioptions.IOStreams, fileName string, namespace string, force bool, dryRunStrategy cmdutil.DryRunStrategy) (*replace.ReplaceOptions, error) {
|
||||
func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmdutil.Factory, ioStreams genericiooptions.IOStreams, fileName string, namespace string, force bool, dryRunStrategy cmdutil.DryRunStrategy) (*replace.ReplaceOptions, error) {
|
||||
o := replace.NewReplaceOptions(ioStreams)
|
||||
|
||||
recorder, err := o.RecordFlags.ToRecorder()
|
||||
|
|
@ -565,7 +566,7 @@ func (k *kubectlResourceOperations) newReplaceOptions(config *rest.Config, f cmd
|
|||
return o, nil
|
||||
}
|
||||
|
||||
func newReconcileOptions(f cmdutil.Factory, kubeClient *kubernetes.Clientset, fileName string, ioStreams genericclioptions.IOStreams, namespace string, dryRunStrategy cmdutil.DryRunStrategy) (*auth.ReconcileOptions, error) {
|
||||
func newReconcileOptions(f cmdutil.Factory, kubeClient *kubernetes.Clientset, fileName string, ioStreams genericiooptions.IOStreams, namespace string, dryRunStrategy cmdutil.DryRunStrategy) (*auth.ReconcileOptions, error) {
|
||||
o := auth.NewReconcileOptions(ioStreams)
|
||||
o.RBACClient = kubeClient.RbacV1()
|
||||
o.NamespaceClient = kubeClient.CoreV1()
|
||||
|
|
@ -626,7 +627,7 @@ func (k *kubectlResourceOperations) authReconcile(ctx context.Context, obj *unst
|
|||
return "", fmt.Errorf("error getting namespace %s: %w", obj.GetNamespace(), err)
|
||||
}
|
||||
}
|
||||
ioStreams := genericclioptions.IOStreams{
|
||||
ioStreams := genericiooptions.IOStreams{
|
||||
In: &bytes.Buffer{},
|
||||
Out: &bytes.Buffer{},
|
||||
ErrOut: &bytes.Buffer{},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package kube
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
|
@ -9,10 +10,14 @@ import (
|
|||
"testing"
|
||||
|
||||
testingutils "github.com/argoproj/argo-cd/gitops-engine/pkg/utils/testing"
|
||||
"github.com/argoproj/argo-cd/gitops-engine/pkg/utils/tracing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/cli-runtime/pkg/genericiooptions"
|
||||
"k8s.io/client-go/rest"
|
||||
cmdutil "k8s.io/kubectl/pkg/cmd/util"
|
||||
)
|
||||
|
|
@ -73,3 +78,94 @@ func TestAuthReconcileWithMissingNamespace(t *testing.T) {
|
|||
_, err = k.authReconcile(context.Background(), clusterRoleBinding, "/dev/null", cmdutil.DryRunNone)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestRBACReconcileUsage(t *testing.T) {
|
||||
var executedCommands []string
|
||||
onKubectlRun := func(cmd string) (CleanupFunc, error) {
|
||||
executedCommands = append(executedCommands, cmd)
|
||||
return func() {}, nil
|
||||
}
|
||||
|
||||
k := &kubectlResourceOperations{
|
||||
onKubectlRun: onKubectlRun,
|
||||
tracer: &tracing.NopTracer{},
|
||||
}
|
||||
|
||||
role := testingutils.NewRole()
|
||||
|
||||
t.Run("CreateResource should NOT call rbacReconcile", func(t *testing.T) {
|
||||
executedCommands = nil
|
||||
_, err := k.runResourceCommand(context.Background(), role, cmdutil.DryRunClient, false, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, cmd := range executedCommands {
|
||||
assert.NotEqual(t, "auth", cmd, "auth reconcile should NOT be called")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ReplaceResource should NOT call rbacReconcile", func(t *testing.T) {
|
||||
executedCommands = nil
|
||||
_, err := k.runResourceCommand(context.Background(), role, cmdutil.DryRunClient, false, func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
for _, cmd := range executedCommands {
|
||||
assert.NotEqual(t, "auth", cmd, "auth reconcile should NOT be called")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Simulation of original issue: when reconcileRBAC is TRUE, it should fail if resource is created by reconcile first", func(t *testing.T) {
|
||||
// This test simulates the BUGGY behavior (passing reconcileRBAC=true to runResourceCommand)
|
||||
// and shows why it fails with "already exists".
|
||||
var executedCommands []string
|
||||
authCalled := false
|
||||
|
||||
kWithAuth := &kubectlResourceOperations{
|
||||
onKubectlRun: func(cmd string) (CleanupFunc, error) {
|
||||
executedCommands = append(executedCommands, cmd)
|
||||
if cmd == "auth" {
|
||||
authCalled = true
|
||||
}
|
||||
return func() {}, nil
|
||||
},
|
||||
tracer: &tracing.NopTracer{},
|
||||
}
|
||||
|
||||
// Mock runResourceCommand behavior manually to avoid calling real authReconcile which panics due to nil fact/config
|
||||
runResourceCommandMock := func(ctx context.Context, obj *unstructured.Unstructured, dryRunStrategy cmdutil.DryRunStrategy, reconcileRBAC bool, executor commandExecutor) (string, error) {
|
||||
if reconcileRBAC && obj.GetAPIVersion() == "rbac.authorization.k8s.io/v1" {
|
||||
_, err := kWithAuth.onKubectlRun("auth")
|
||||
require.NoError(t, err)
|
||||
}
|
||||
ioStreams := genericiooptions.IOStreams{
|
||||
In: &bytes.Buffer{},
|
||||
Out: &bytes.Buffer{},
|
||||
ErrOut: &bytes.Buffer{},
|
||||
}
|
||||
return "", executor(ioStreams, "")
|
||||
}
|
||||
|
||||
executor := func(ioStreams genericiooptions.IOStreams, fileName string) error {
|
||||
if authCalled {
|
||||
// Simulate the "already exists" error that happens when kubectl create/replace
|
||||
// is called after kubectl auth reconcile has already created the resource.
|
||||
return fmt.Errorf("roles.rbac.authorization.k8s.io \"mytestrole\" already exists")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If we call it with reconcileRBAC = true (the bug), it should fail
|
||||
_, err := runResourceCommandMock(context.Background(), role, cmdutil.DryRunClient, true, executor)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "already exists")
|
||||
|
||||
// If we call it with reconcileRBAC = false (the fix), it should succeed
|
||||
authCalled = false
|
||||
executedCommands = nil
|
||||
_, err = runResourceCommandMock(context.Background(), role, cmdutil.DryRunClient, false, executor)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
27
go.mod
27
go.mod
|
|
@ -7,7 +7,7 @@ require (
|
|||
dario.cat/mergo v1.0.2
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.21.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.13.1
|
||||
github.com/Azure/kubelogin v0.2.15
|
||||
github.com/Azure/kubelogin v0.2.16
|
||||
github.com/Masterminds/semver/v3 v3.4.0
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/TomOnTime/utfutil v1.0.0
|
||||
|
|
@ -16,10 +16,9 @@ require (
|
|||
github.com/argoproj/notifications-engine v0.5.1-0.20260213231747-1dbe3de712f8
|
||||
github.com/argoproj/pkg v0.13.6
|
||||
github.com/argoproj/pkg/v2 v2.0.1
|
||||
github.com/aws/aws-sdk-go v1.55.7
|
||||
github.com/bmatcuk/doublestar/v4 v4.10.0
|
||||
github.com/bombsimon/logrusr/v4 v4.1.0
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.17.0
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.18.0
|
||||
github.com/casbin/casbin/v2 v2.135.0
|
||||
github.com/casbin/govaluate v1.10.0
|
||||
github.com/cenkalti/backoff/v5 v5.0.3
|
||||
|
|
@ -96,11 +95,11 @@ require (
|
|||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.42.0
|
||||
go.opentelemetry.io/otel/sdk v1.42.0
|
||||
go.opentelemetry.io/otel/trace v1.42.0
|
||||
golang.org/x/crypto v0.48.0
|
||||
golang.org/x/net v0.51.0
|
||||
golang.org/x/crypto v0.49.0
|
||||
golang.org/x/net v0.52.0
|
||||
golang.org/x/oauth2 v0.36.0
|
||||
golang.org/x/sync v0.20.0
|
||||
golang.org/x/term v0.40.0
|
||||
golang.org/x/term v0.41.0
|
||||
golang.org/x/time v0.15.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57
|
||||
google.golang.org/grpc v1.79.2
|
||||
|
|
@ -211,7 +210,6 @@ require (
|
|||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/golang/glog v1.2.5 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/google/go-github/v75 v75.0.0 // indirect
|
||||
github.com/google/go-querystring v1.2.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
|
|
@ -226,7 +224,6 @@ require (
|
|||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/itchyny/timefmt-go v0.1.7 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/jonboulle/clockwork v0.5.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
|
|
@ -282,12 +279,13 @@ require (
|
|||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.42.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.42.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/tools v0.41.0 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/tools v0.42.0 // indirect
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated // indirect
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
|
||||
gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45 // indirect
|
||||
|
|
@ -317,10 +315,13 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.10
|
||||
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.31.8
|
||||
github.com/oklog/ulid/v2 v2.1.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
)
|
||||
|
||||
require github.com/google/go-github/v84 v84.0.0 // indirect
|
||||
|
||||
replace (
|
||||
github.com/golang/protobuf => github.com/golang/protobuf v1.5.4
|
||||
github.com/grpc-ecosystem/grpc-gateway => github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
|
|
|
|||
44
go.sum
44
go.sum
|
|
@ -72,8 +72,8 @@ github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+Z
|
|||
github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/Azure/kubelogin v0.2.15 h1:oJqD8Dvput3rO/xZgMTU+hBrcgg0BfQGPCNHJ2dEmys=
|
||||
github.com/Azure/kubelogin v0.2.15/go.mod h1:RwJS8TzSHTVQhfIZA4HLS79QGfvIp0ocIVLT5oHS/ls=
|
||||
github.com/Azure/kubelogin v0.2.16 h1:z0jwNQ9A7LvIqS0Go+6CPZv0TuQQRL2mc+zY9wjBuF8=
|
||||
github.com/Azure/kubelogin v0.2.16/go.mod h1:UvizZ5Gu/2btUFXm2cccbxliK/ensgBD5NTCihZoONE=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.6.0 h1:XRzhVemXdgvJqCH0sFfrBUTnUJSBrBf7++ypk+twtRs=
|
||||
|
|
@ -124,8 +124,6 @@ github.com/argoproj/pkg/v2 v2.0.1/go.mod h1:sdifF6sUTx9ifs38ZaiNMRJuMpSCBB9GulHf
|
|||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/aws/aws-sdk-go v1.44.39/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||
github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE=
|
||||
github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.3/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.32.11 h1:ftxI5sgz8jZkckuUHXfC/wMUc8u3fG1vQS0plr2F2Zs=
|
||||
|
|
@ -140,10 +138,14 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJ
|
|||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.10 h1:hAK/gb7zTE3zIU3tKuG1+62NHyQ+03Ew1YiJZVNmd04=
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.10/go.mod h1:UgLONgXRd26X5Zz/RG29duwo+mK5ZbqSRGOs/sVl6Uw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7suZk9UCJHE1Iw9GMZJJl0dAnKXXP1NaSDHwmw=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA=
|
||||
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.31.8 h1:mGgiunl7ZwOwhpJwJNF4JfsZFYJp08wjyS3NqFQe3ws=
|
||||
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.31.8/go.mod h1:KdM2EhXeHfeBQz5keOvv/FM7kbesjCWm7HEEyJe3frs=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row=
|
||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU=
|
||||
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.1 h1:ZtgZeMPJH8+/vNs9vJFFLI0QEzYbcN0p7x1/FFwyROc=
|
||||
|
|
@ -168,8 +170,8 @@ github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6
|
|||
github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bombsimon/logrusr/v4 v4.1.0 h1:uZNPbwusB0eUXlO8hIUwStE6Lr5bLN6IgYgG+75kuh4=
|
||||
github.com/bombsimon/logrusr/v4 v4.1.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.17.0 h1:SmbUK/GxpAspRjSQbB6ARvH+ArzlNzTtHydNyXUQ6zg=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.17.0/go.mod h1:vuD/xvJT9Y+ZVZRv4HQ42cMyPFIYqpc7AbB4Gvt/DlY=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.18.0 h1:WPqnN6NS9XvYlOgZQAIseN7Z1uAiE+UxgDKlW7FvFuU=
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.18.0/go.mod h1:gpoSwwWc4biE49F7n+roCcpkEkZ1Qr9soZ2ESvMiouU=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
|
|
@ -473,8 +475,8 @@ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v69 v69.2.0 h1:wR+Wi/fN2zdUx9YxSmYE0ktiX9IAR/BeePzeaUUbEHE=
|
||||
github.com/google/go-github/v69 v69.2.0/go.mod h1:xne4jymxLR6Uj9b7J7PyTpkMYstEMMwGZa0Aehh1azM=
|
||||
github.com/google/go-github/v75 v75.0.0 h1:k7q8Bvg+W5KxRl9Tjq16a9XEgVY1pwuiG5sIL7435Ic=
|
||||
github.com/google/go-github/v75 v75.0.0/go.mod h1:H3LUJEA1TCrzuUqtdAQniBNwuKiQIqdGKgBo1/M/uqI=
|
||||
github.com/google/go-github/v84 v84.0.0 h1:I/0Xn5IuChMe8TdmI2bbim5nyhaRFJ7DEdzmD2w+yVA=
|
||||
github.com/google/go-github/v84 v84.0.0/go.mod h1:WwYL1z1ajRdlaPszjVu/47x1L0PXukJBn73xsiYrRRQ=
|
||||
github.com/google/go-jsonnet v0.21.0 h1:43Bk3K4zMRP/aAZm9Po2uSEjY6ALCkYUVIcz9HLGMvA=
|
||||
github.com/google/go-jsonnet v0.21.0/go.mod h1:tCGAu8cpUpEZcdGMmdOu37nh8bGgqubhI5v2iSk3KJQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
|
|
@ -583,9 +585,7 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
|
|||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jeremywohl/flatten v1.0.2-0.20211013061545-07e4a09fb8e4 h1:4mRgApcowAtxNLwOQ93jhHMLFgkX2D5yM53mtZSk6Nw=
|
||||
github.com/jeremywohl/flatten v1.0.2-0.20211013061545-07e4a09fb8e4/go.mod h1:4AmD/VxjWcI5SRB0n6szE2A6s2fsNHDLO0nAlMHgfLQ=
|
||||
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||
github.com/jonboulle/clockwork v0.5.0 h1:Hyh9A8u51kptdkR+cqRpT1EebBwTn1oK9YfGYbdFz6I=
|
||||
|
|
@ -1030,8 +1030,8 @@ golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7
|
|||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
|
@ -1074,8 +1074,8 @@ golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
|||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -1141,8 +1141,8 @@ golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
|||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
@ -1250,8 +1250,8 @@ golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
|||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsOKwuR5X/m0QFOJpSZvAxFfkQT+Erd9D4=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
|
@ -1278,8 +1278,8 @@ golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
|||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
||||
golang.org/x/term v0.41.0 h1:QCgPso/Q3RTJx2Th4bDLqML4W6iJiaXFq2/ftQF13YU=
|
||||
golang.org/x/term v0.41.0/go.mod h1:3pfBgksrReYfZ5lvYM0kSO0LIkAl4Yl2bXOkKP7Ec2A=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
@ -1304,8 +1304,8 @@ golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
|||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
|
|
|||
|
|
@ -48,6 +48,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
@ -96,4 +102,4 @@ spec:
|
|||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
nodeSelector:
|
||||
kubernetes.io/os: linux
|
||||
kubernetes.io/os: linux
|
||||
|
|
|
|||
6
manifests/ha/install-with-hydrator.yaml
generated
6
manifests/ha/install-with-hydrator.yaml
generated
|
|
@ -33129,6 +33129,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/ha/install.yaml
generated
6
manifests/ha/install.yaml
generated
|
|
@ -32959,6 +32959,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
|
|
@ -2376,6 +2376,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/ha/namespace-install.yaml
generated
6
manifests/ha/namespace-install.yaml
generated
|
|
@ -2206,6 +2206,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/install-with-hydrator.yaml
generated
6
manifests/install-with-hydrator.yaml
generated
|
|
@ -32147,6 +32147,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/install.yaml
generated
6
manifests/install.yaml
generated
|
|
@ -31975,6 +31975,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/namespace-install-with-hydrator.yaml
generated
6
manifests/namespace-install-with-hydrator.yaml
generated
|
|
@ -1394,6 +1394,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
6
manifests/namespace-install.yaml
generated
6
manifests/namespace-install.yaml
generated
|
|
@ -1222,6 +1222,12 @@ spec:
|
|||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_NOTIFICATION_CONTROLLER_PROCESSORS_COUNT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: notificationscontroller.processors.count
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_LOG_FORMAT_TIMESTAMP
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@
|
|||
],
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"description": "Ignore gitops-engine: local replace (./gitops-engine), digest bumps are not applicable.",
|
||||
"matchDatasources": ["go"],
|
||||
"matchPackageNames": ["github.com/argoproj/argo-cd/gitops-engine"],
|
||||
"enabled": false
|
||||
},
|
||||
{
|
||||
"description": "Run make mockgen after updating mockery",
|
||||
"matchDatasources": [
|
||||
|
|
|
|||
|
|
@ -1583,14 +1583,15 @@ func (server *ArgoCDServer) getClaims(ctx context.Context) (jwt.Claims, string,
|
|||
}
|
||||
|
||||
finalClaims := claims
|
||||
if server.settings.IsSSOConfigured() {
|
||||
oidcConfig := server.settings.OIDCConfig()
|
||||
if oidcConfig != nil || server.settings.IsDexConfigured() {
|
||||
updatedClaims, err := server.ssoClientApp.SetGroupsFromUserInfo(ctx, claims, util_session.SessionManagerClaimsIssuer)
|
||||
if err != nil {
|
||||
return claims, "", status.Errorf(codes.Unauthenticated, "invalid session: %v", err)
|
||||
}
|
||||
finalClaims = updatedClaims
|
||||
// OIDC tokens are automatically refreshed here prior to expiration
|
||||
refreshedToken, err := server.ssoClientApp.CheckAndRefreshToken(ctx, updatedClaims, server.settings.OIDCRefreshTokenThreshold)
|
||||
refreshedToken, err := server.ssoClientApp.CheckAndRefreshToken(ctx, updatedClaims, server.settings.RefreshTokenThresholdWithConfig(oidcConfig))
|
||||
if err != nil {
|
||||
log.Errorf("error checking and refreshing token: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu
|
|||
# Please make sure to also check the contained yarn version and update the references below when upgrading this image's version
|
||||
FROM docker.io/library/node:22.9.0@sha256:8398ea18b8b72817c84af283f72daed9629af2958c4f618fe6db4f453c5c9328 AS node
|
||||
|
||||
FROM docker.io/library/golang:1.26.1@sha256:e2ddb153f786ee6210bf8c40f7f35490b3ff7d38be70d1a0d358ba64225f6428 AS golang
|
||||
FROM docker.io/library/golang:1.26.1@sha256:c7e98cc0fd4dfb71ee7465fee6c9a5f079163307e4bf141b336bb9dae00159a5 AS golang
|
||||
|
||||
FROM docker.io/library/registry:3.0@sha256:6c5666b861f3505b116bb9aa9b25175e71210414bd010d92035ff64018f9457e AS registry
|
||||
|
||||
|
|
|
|||
|
|
@ -3087,11 +3087,9 @@ func TestDeletionConfirmation(t *testing.T) {
|
|||
t.Context(), &corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test-configmap",
|
||||
Labels: map[string]string{
|
||||
common.LabelKeyAppInstance: ctx.AppName(),
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
AnnotationSyncOptions: "Prune=confirm",
|
||||
common.AnnotationKeyAppInstance: fmt.Sprintf("%s:/ConfigMap:%s/test-configmap", ctx.GetName(), ctx.DeploymentNamespace()),
|
||||
AnnotationSyncOptions: "Prune=confirm",
|
||||
},
|
||||
},
|
||||
}, metav1.CreateOptions{})
|
||||
|
|
@ -3102,7 +3100,8 @@ func TestDeletionConfirmation(t *testing.T) {
|
|||
When().
|
||||
PatchFile("guestbook-ui-deployment.yaml", `[{ "op": "add", "path": "/metadata/annotations", "value": { "argocd.argoproj.io/sync-options": "Delete=confirm" }}]`).
|
||||
CreateApp().Sync().
|
||||
Then().ExpectConsistently(OperationPhaseIs(OperationRunning), time.Second, 5*time.Second).
|
||||
Then().
|
||||
ExpectConsistently(OperationPhaseIs(OperationRunning), time.Second, 5*time.Second).
|
||||
When().ConfirmDeletion().
|
||||
Then().Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
|
|
|
|||
|
|
@ -443,9 +443,10 @@ func (a *Actions) ConfirmDeletion() *Actions {
|
|||
|
||||
a.runCli("app", "confirm-deletion", a.context.AppQualifiedName())
|
||||
|
||||
// Always sleep more than a second after the confirmation so the timestamp
|
||||
// is not valid for immediate subsequent operations
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
// Always sleep a few seconds after the confirmation so the timestamp
|
||||
// is not valid for immediate subsequent operations.
|
||||
// Kubernetes containers may have clocks with a few seconds difference, and we want to avoid race conditions.
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
return a
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,18 +58,21 @@ func (c *Consequences) Expect(e Expectation) *Consequences {
|
|||
return c
|
||||
}
|
||||
|
||||
// ExpectConsistently will continuously evaluate a condition, and it must be true each time it is evaluated, otherwise the test is failed. The condition will be repeatedly evaluated until 'expirationDuration' is met, waiting 'waitDuration' after each success.
|
||||
// ExpectConsistently will continuously evaluate a condition. Once true, it must be true each time it is evaluated, otherwise the test is failed.
|
||||
// The condition will be repeatedly evaluated once it is true,until 'expirationDuration' is met, waiting 'waitDuration' after each success.
|
||||
func (c *Consequences) ExpectConsistently(e Expectation, waitDuration time.Duration, expirationDuration time.Duration) *Consequences {
|
||||
// this invocation makes sure this func is not reported as the cause of the failure - we are a "test helper"
|
||||
c.context.T().Helper()
|
||||
|
||||
c.Expect(e) // ensure the condition is true before expecting consistency
|
||||
|
||||
expiration := time.Now().Add(expirationDuration)
|
||||
for time.Now().Before(expiration) {
|
||||
state, message := e(c)
|
||||
switch state {
|
||||
case succeeded:
|
||||
log.Infof("expectation succeeded: %s", message)
|
||||
case failed:
|
||||
default:
|
||||
c.context.T().Fatalf("failed expectation: %s", message)
|
||||
return c
|
||||
}
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@ func TestAutomatedSelfHealingAgainstAnnotatedTag(t *testing.T) {
|
|||
app.Spec.SyncPolicy = &SyncPolicy{Automated: &SyncPolicyAutomated{Prune: true, SelfHeal: false}}
|
||||
}).
|
||||
Then().
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
ExpectConsistently(SyncStatusIs(SyncStatusCodeSynced), WaitDuration, time.Second*10).
|
||||
When().
|
||||
// Update the annotated tag to a new git commit, that has a new revisionHistoryLimit.
|
||||
|
|
@ -220,7 +219,6 @@ func TestAutomatedSelfHealingAgainstLightweightTag(t *testing.T) {
|
|||
app.Spec.SyncPolicy = &SyncPolicy{Automated: &SyncPolicyAutomated{Prune: true, SelfHeal: false}}
|
||||
}).
|
||||
Then().
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
ExpectConsistently(SyncStatusIs(SyncStatusCodeSynced), WaitDuration, time.Second*10).
|
||||
When().
|
||||
// Update the annotated tag to a new git commit, that has a new revisionHistoryLimit.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
ARG BASE_IMAGE=docker.io/library/ubuntu:25.10@sha256:4a9232cc47bf99defcc8860ef6222c99773330367fcecbf21ba2edb0b810a31e
|
||||
|
||||
FROM docker.io/library/golang:1.26.0@sha256:c83e68f3ebb6943a2904fa66348867d108119890a2c6a2e6f07b38d0eb6c25c5 AS go
|
||||
FROM docker.io/library/golang:1.26.0@sha256:fb612b7831d53a89cbc0aaa7855b69ad7b0caf603715860cf538df854d047b84 AS go
|
||||
|
||||
RUN go install github.com/mattn/goreman@latest && \
|
||||
go install github.com/kisielk/godepgraph@latest
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ func NewClientApp(settings *settings.ArgoCDSettings, dexServerAddr string, dexTL
|
|||
clientCache: cacheClient,
|
||||
azure: azureApp{mtx: &sync.RWMutex{}},
|
||||
domainHint: domainHint,
|
||||
refreshTokenThreshold: settings.OIDCRefreshTokenThreshold,
|
||||
refreshTokenThreshold: settings.RefreshTokenThreshold(),
|
||||
}
|
||||
log.Infof("Creating client app (%s)", a.clientID)
|
||||
u, err := url.Parse(settings.URL)
|
||||
|
|
|
|||
|
|
@ -136,9 +136,6 @@ type ArgoCDSettings struct {
|
|||
// token verification to pass despite the OIDC provider having an invalid certificate. Only set to `true` if you
|
||||
// understand the risks.
|
||||
OIDCTLSInsecureSkipVerify bool `json:"oidcTLSInsecureSkipVerify"`
|
||||
// OIDCRefreshTokenThreshold sets the threshold for preemptive server-side token refresh. If set to 0, tokens
|
||||
// will not be refreshed and will expire before client is redirected to login.
|
||||
OIDCRefreshTokenThreshold time.Duration `json:"oidcRefreshTokenThreshold,omitempty"`
|
||||
// AppsInAnyNamespaceEnabled indicates whether applications are allowed to be created in any namespace
|
||||
AppsInAnyNamespaceEnabled bool `json:"appsInAnyNamespaceEnabled"`
|
||||
// ExtensionConfig configurations related to ArgoCD proxy extensions. The keys are the extension name.
|
||||
|
|
@ -1484,7 +1481,6 @@ func getDownloadBinaryUrlsFromConfigMap(argoCDCM *corev1.ConfigMap) map[string]s
|
|||
func updateSettingsFromConfigMap(settings *ArgoCDSettings, argoCDCM *corev1.ConfigMap) {
|
||||
settings.DexConfig = argoCDCM.Data[settingDexConfigKey]
|
||||
settings.OIDCConfigRAW = argoCDCM.Data[settingsOIDCConfigKey]
|
||||
settings.OIDCRefreshTokenThreshold = settings.RefreshTokenThreshold()
|
||||
settings.KustomizeBuildOptions = argoCDCM.Data[kustomizeBuildOptionsKey]
|
||||
settings.StatusBadgeEnabled = argoCDCM.Data[statusBadgeEnabledKey] == "true"
|
||||
settings.StatusBadgeRootUrl = argoCDCM.Data[statusBadgeRootURLKey]
|
||||
|
|
@ -1937,7 +1933,12 @@ func (a *ArgoCDSettings) UserInfoCacheExpiration() time.Duration {
|
|||
|
||||
// RefreshTokenThreshold returns the duration before token expiration that a token should be refreshed by the server
|
||||
func (a *ArgoCDSettings) RefreshTokenThreshold() time.Duration {
|
||||
if oidcConfig := a.OIDCConfig(); oidcConfig != nil && oidcConfig.RefreshTokenThreshold != "" {
|
||||
return a.RefreshTokenThresholdWithConfig(a.OIDCConfig())
|
||||
}
|
||||
|
||||
// RefreshTokenThresholdWithConfig takes oidcConfig as param and returns the duration before token expiration that a token should be refreshed by the server
|
||||
func (a *ArgoCDSettings) RefreshTokenThresholdWithConfig(oidcConfig *OIDCConfig) time.Duration {
|
||||
if oidcConfig != nil && oidcConfig.RefreshTokenThreshold != "" {
|
||||
refreshTokenThreshold, err := time.ParseDuration(oidcConfig.RefreshTokenThreshold)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to parse 'oidc.config.refreshTokenThreshold' key: %v", err)
|
||||
|
|
|
|||
Loading…
Reference in a new issue