Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/argoproj/argo-cd
Browse files Browse the repository at this point in the history
  • Loading branch information
reggie-k committed Sep 30, 2024
2 parents 1149f46 + fa54ce2 commit 04164d9
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 18 deletions.
4 changes: 4 additions & 0 deletions docs/operator-manual/upgrading/2.12-2.13.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# v2.12 to 2.13

## Upgraded Helm Version

Note that bundled Helm version has been upgraded from 3.15.2 to 3.15.4.

## Custom Resource Actions for Flux Resources

[`Custom Resource Actions`](../resource_actions.md#Custom-Resource-Actions) have been added for Flux Resources.
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/diff-strategies.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Argo CD currently has 3 different strategies to calculate diffs:
## Structured-Merge Diff
*Current Status: [Beta][1] (Since v2.5.0)*

This is diff strategy is automatically used when Server-Side Apply
This diff strategy is automatically used when Server-Side Apply
sync option is enabled. It uses the [structured-merge-diff][2] library
used by Kubernetes to calculate diffs based on fields ownership. There
are some challenges using this strategy to calculate diffs for CRDs
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1bc3f354f7ce4d7fd9cfa5bcc701c1f32c88d27076d96c2792d5b5226062aee5 helm-v3.15.4-darwin-amd64.tar.gz
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
88115846a1fb58f8eb8f64fec5c343d95ca394f1be811602fa54a887c98730ac helm-v3.15.4-darwin-arm64.tar.gz
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
11400fecfc07fd6f034863e4e0c4c4445594673fd2a129e701fe41f31170cfa9 helm-v3.15.4-linux-amd64.tar.gz
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fa419ecb139442e8a594c242343fafb7a46af3af34041c4eac1efcc49d74e626 helm-v3.15.4-linux-arm64.tar.gz
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e4efce93723f52dd858e9046ea836c9c75f346facce1b87b8cf78c817b97e6ac helm-v3.15.4-linux-ppc64le.tar.gz
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
c6e0cdea598196895ac7b627ce972699ef9f06b0eba51dc4db7cc21b3369f24a helm-v3.15.4-linux-s390x.tar.gz
2 changes: 1 addition & 1 deletion hack/tool-versions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# Use ./hack/installers/checksums/add-helm-checksums.sh and
# add-kustomize-checksums.sh to help download checksums.
###############################################################################
helm3_version=3.15.2
helm3_version=3.15.4
kubectl_version=1.17.8
kubectx_version=0.6.3
kustomize5_version=5.4.3
Expand Down
16 changes: 13 additions & 3 deletions server/extension/extension.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ const (
DefaultIdleConnectionTimeout = 60 * time.Second
DefaultMaxIdleConnections = 30

// HeaderArgoCDNamespace defines the namespace of the
// argo control plane to be passed to the extension handler.
// Example:
// Argocd-Namespace: "namespace"
HeaderArgoCDNamespace = "Argocd-Namespace"

// HeaderArgoCDApplicationName defines the name of the
// expected application header to be passed to the extension
// handler. The header value must follow the format:
Expand Down Expand Up @@ -333,6 +339,7 @@ type RbacEnforcer interface {
// and handling proxy extensions.
type Manager struct {
log *log.Entry
namespace string
settings SettingsGetter
application ApplicationGetter
project ProjectGetter
Expand All @@ -355,9 +362,10 @@ type ExtensionMetricsRegistry interface {
}

// NewManager will initialize a new manager.
func NewManager(log *log.Entry, sg SettingsGetter, ag ApplicationGetter, pg ProjectGetter, rbac RbacEnforcer, ug UserGetter) *Manager {
func NewManager(log *log.Entry, namespace string, sg SettingsGetter, ag ApplicationGetter, pg ProjectGetter, rbac RbacEnforcer, ug UserGetter) *Manager {
return &Manager{
log: log,
namespace: namespace,
settings: sg,
application: ag,
project: pg,
Expand Down Expand Up @@ -740,7 +748,7 @@ func (m *Manager) CallExtension() func(http.ResponseWriter, *http.Request) {

user := m.userGetter.GetUser(r.Context())
groups := m.userGetter.GetGroups(r.Context())
prepareRequest(r, extName, app, user, groups)
prepareRequest(r, m.namespace, extName, app, user, groups)
m.log.Debugf("proxing request for extension %q", extName)
// httpsnoop package is used to properly wrap the responseWriter
// and avoid optional intefaces issue:
Expand All @@ -763,11 +771,13 @@ func registerMetrics(extName string, metrics httpsnoop.Metrics, extensionMetrics
// the Argo CD extension API section from it. It provides additional information to
// the backend service appending them in the outgoing request headers. The appended
// headers are:
// - Control plane namespace
// - Cluster destination name
// - Cluster destination server
// - Argo CD authenticated username
func prepareRequest(r *http.Request, extName string, app *v1alpha1.Application, username string, groups []string) {
func prepareRequest(r *http.Request, namespace string, extName string, app *v1alpha1.Application, username string, groups []string) {
r.URL.Path = strings.TrimPrefix(r.URL.Path, fmt.Sprintf("%s/%s", URLPrefix, extName))
r.Header.Set(HeaderArgoCDNamespace, namespace)
if app.Spec.Destination.Name != "" {
r.Header.Set(HeaderArgoCDTargetClusterName, app.Spec.Destination.Name)
}
Expand Down
6 changes: 4 additions & 2 deletions server/extension/extension_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func TestRegisterExtensions(t *testing.T) {

logger, _ := test.NewNullLogger()
logEntry := logger.WithContext(context.Background())
m := extension.NewManager(logEntry, settMock, nil, nil, nil, nil)
m := extension.NewManager(logEntry, "", settMock, nil, nil, nil, nil)

return &fixture{
settingsGetterMock: settMock,
Expand Down Expand Up @@ -248,6 +248,7 @@ func TestCallExtension(t *testing.T) {
userMock *mocks.UserGetter
manager *extension.Manager
}
defaultServerNamespace := "control-plane-ns"
defaultProjectName := "project-name"

setup := func() *fixture {
Expand All @@ -260,7 +261,7 @@ func TestCallExtension(t *testing.T) {

logger, _ := test.NewNullLogger()
logEntry := logger.WithContext(context.Background())
m := extension.NewManager(logEntry, settMock, appMock, projMock, rbacMock, userMock)
m := extension.NewManager(logEntry, defaultServerNamespace, settMock, appMock, projMock, rbacMock, userMock)
m.AddMetricsRegistry(metricsMock)

mux := http.NewServeMux()
Expand Down Expand Up @@ -444,6 +445,7 @@ func TestCallExtension(t *testing.T) {
require.NoError(t, err)
actual := strings.TrimSuffix(string(body), "\n")
assert.Equal(t, backendResponse, actual)
assert.Equal(t, defaultServerNamespace, resp.Header.Get(extension.HeaderArgoCDNamespace))
assert.Equal(t, clusterURL, resp.Header.Get(extension.HeaderArgoCDTargetClusterURL))
assert.Equal(t, "Bearer some-bearer-token", resp.Header.Get("Authorization"))
assert.Equal(t, "some-user", resp.Header.Get(extension.HeaderArgoCDUsername))
Expand Down
2 changes: 1 addition & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ func NewServer(ctx context.Context, opts ArgoCDServerOpts, appsetOpts Applicatio
ag := extension.NewDefaultApplicationGetter(appLister)
pg := extension.NewDefaultProjectGetter(projLister, dbInstance)
ug := extension.NewDefaultUserGetter(policyEnf)
em := extension.NewManager(logger, sg, ag, pg, enf, ug)
em := extension.NewManager(logger, opts.Namespace, sg, ag, pg, enf, ug)

a := &ArgoCDServer{
ArgoCDServerOpts: opts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ export class ProjectDetails extends React.Component<RouteComponentProps<{name: s
/>
<AuthSettingsCtx.Consumer>
{authCtx =>
authCtx.appsInAnyNamespaceEnabled && (
authCtx?.appsInAnyNamespaceEnabled && (
<EditablePanel
save={item => this.saveProject(item)}
values={proj}
Expand Down
23 changes: 17 additions & 6 deletions util/helm/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"gopkg.in/yaml.v2"
"oras.land/oras-go/v2/registry/remote"
"oras.land/oras-go/v2/registry/remote/auth"
"oras.land/oras-go/v2/registry/remote/credentials"

"github.com/argoproj/argo-cd/v2/util/cache"
argoio "github.com/argoproj/argo-cd/v2/util/io"
Expand Down Expand Up @@ -447,13 +448,23 @@ func (c *nativeHelmChart) GetTags(chart string, noCache bool) (*TagsList, error)
}}

repoHost, _, _ := strings.Cut(tagsURL, "/")
credential := auth.StaticCredential(repoHost, auth.Credential{
Username: c.creds.Username,
Password: c.creds.Password,
})

// Try to fallback to the environment config, but we shouldn't error if the file is not set
if c.creds.Username == "" && c.creds.Password == "" {
store, _ := credentials.NewStoreFromDocker(credentials.StoreOptions{})
if store != nil {
credential = credentials.Credential(store)
}
}

repo.Client = &auth.Client{
Client: client,
Cache: nil,
Credential: auth.StaticCredential(repoHost, auth.Credential{
Username: c.creds.Username,
Password: c.creds.Password,
}),
Client: client,
Cache: nil,
Credential: credential,
}

ctx := context.Background()
Expand Down
97 changes: 94 additions & 3 deletions util/helm/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http/httptest"
"net/url"
"os"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -214,6 +215,91 @@ func TestGetTagsFromUrl(t *testing.T) {
}

func TestGetTagsFromURLPrivateRepoAuthentication(t *testing.T) {
username := "my-username"
password := "my-password"
expectedAuthorization := "Basic bXktdXNlcm5hbWU6bXktcGFzc3dvcmQ=" // base64(user:password)
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Logf("called %s", r.URL.Path)

authorization := r.Header.Get("Authorization")

if authorization == "" {
w.Header().Set("WWW-Authenticate", `Basic realm="helm repo to get tags"`)
w.WriteHeader(http.StatusUnauthorized)
return
}

assert.Equal(t, expectedAuthorization, authorization)

responseTags := TagsList{
Tags: []string{
"2.8.0",
"2.8.0-prerelease",
"2.8.0_build",
"2.8.0-prerelease_build",
"2.8.0-prerelease.1_build.1234",
},
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
err := json.NewEncoder(w).Encode(responseTags)
if err != nil {
t.Fatal(err)
}
}))
t.Cleanup(server.Close)

serverURL, err := url.Parse(server.URL)
require.NoError(t, err)

testCases := []struct {
name string
repoURL string
}{
{
name: "should login correctly when the repo path is in the server root with http scheme",
repoURL: server.URL,
},
{
name: "should login correctly when the repo path is not in the server root with http scheme",
repoURL: fmt.Sprintf("%s/my-repo", server.URL),
},
{
name: "should login correctly when the repo path is in the server root without http scheme",
repoURL: serverURL.Host,
},
{
name: "should login correctly when the repo path is not in the server root without http scheme",
repoURL: fmt.Sprintf("%s/my-repo", serverURL.Host),
},
}

for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
client := NewClient(testCase.repoURL, Creds{
InsecureSkipVerify: true,
Username: username,
Password: password,
}, true, "", "")

tags, err := client.GetTags("mychart", true)

require.NoError(t, err)
assert.ElementsMatch(t, tags.Tags, []string{
"2.8.0",
"2.8.0-prerelease",
"2.8.0+build",
"2.8.0-prerelease+build",
"2.8.0-prerelease.1+build.1234",
})
})
}
}

func TestGetTagsFromURLEnvironmentAuthentication(t *testing.T) {
bearerToken := "Zm9vOmJhcg=="
expectedAuthorization := "Basic " + bearerToken
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
t.Logf("called %s", r.URL.Path)

Expand All @@ -224,7 +310,7 @@ func TestGetTagsFromURLPrivateRepoAuthentication(t *testing.T) {
return
}

t.Logf("authorization received %s", authorization)
assert.Equal(t, expectedAuthorization, authorization)

responseTags := TagsList{
Tags: []string{
Expand All @@ -248,6 +334,13 @@ func TestGetTagsFromURLPrivateRepoAuthentication(t *testing.T) {
serverURL, err := url.Parse(server.URL)
require.NoError(t, err)

tempDir := t.TempDir()
configPath := filepath.Join(tempDir, "config.json")
t.Setenv("DOCKER_CONFIG", tempDir)

config := fmt.Sprintf(`{"auths":{"%s":{"auth":"%s"}}}`, server.URL, bearerToken)
require.NoError(t, os.WriteFile(configPath, []byte(config), 0o666))

testCases := []struct {
name string
repoURL string
Expand All @@ -274,8 +367,6 @@ func TestGetTagsFromURLPrivateRepoAuthentication(t *testing.T) {
t.Run(testCase.name, func(t *testing.T) {
client := NewClient(testCase.repoURL, Creds{
InsecureSkipVerify: true,
Username: "my-username",
Password: "my-password",
}, true, "", "")

tags, err := client.GetTags("mychart", true)
Expand Down

0 comments on commit 04164d9

Please sign in to comment.