Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: settings API should not fail if repo server is not available #12164

Merged
merged 1 commit into from
Jan 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions assets/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -3588,6 +3588,29 @@
}
}
},
"/api/v1/settings/plugins": {
"get": {
"tags": [
"SettingsService"
],
"summary": "Get returns Argo CD plugins",
"operationId": "SettingsService_GetPlugins",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
"$ref": "#/definitions/clusterSettingsPluginsResponse"
}
},
"default": {
"description": "An unexpected error response.",
"schema": {
"$ref": "#/definitions/runtimeError"
}
}
}
}
},
"/api/v1/stream/applications": {
"get": {
"tags": [
Expand Down Expand Up @@ -4342,6 +4365,17 @@
}
}
},
"clusterSettingsPluginsResponse": {
"type": "object",
"properties": {
"plugins": {
"type": "array",
"items": {
"$ref": "#/definitions/clusterPlugin"
}
}
}
},
"gpgkeyGnuPGPublicKeyCreateResponse": {
"type": "object",
"title": "Response to a public key creation request",
Expand Down
389 changes: 311 additions & 78 deletions pkg/apiclient/settings/settings.pb.go

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions pkg/apiclient/settings/settings.pb.gw.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 37 additions & 21 deletions server/settings/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"fmt"

"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
ioutil "github.com/argoproj/argo-cd/v2/util/io"
"github.com/ghodss/yaml"
"github.com/golang/protobuf/ptypes/empty"

"github.com/ghodss/yaml"
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
ioutil "github.com/argoproj/argo-cd/v2/util/io"

sessionmgr "github.com/argoproj/argo-cd/v2/util/session"

Expand Down Expand Up @@ -62,7 +62,7 @@ func (s *Server) Get(ctx context.Context, q *settingspkg.SettingsQuery) (*settin
if err != nil {
return nil, err
}
plugins, err := s.plugins(ctx)
plugins, err := s.plugins(ctx, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -158,29 +158,41 @@ func (s *Server) Get(ctx context.Context, q *settingspkg.SettingsQuery) (*settin
return &set, nil
}

func (s *Server) plugins(ctx context.Context) ([]*settingspkg.Plugin, error) {
in, err := s.mgr.GetConfigManagementPlugins()
// GetPlugins returns a list of plugins
func (s *Server) GetPlugins(ctx context.Context, q *settingspkg.SettingsQuery) (*settingspkg.SettingsPluginsResponse, error) {
plugins, err := s.plugins(ctx, true)
if err != nil {
return nil, err
}
closer, client, err := s.repoClient.NewRepoServerClient()
if err != nil {
return nil, fmt.Errorf("error creating repo server client: %w", err)
}
defer ioutil.Close(closer)
return &settingspkg.SettingsPluginsResponse{Plugins: plugins}, nil
}

pluginList, err := client.ListPlugins(ctx, &empty.Empty{})
func (s *Server) plugins(ctx context.Context, includeV2Plugins bool) ([]*settingspkg.Plugin, error) {
in, err := s.mgr.GetConfigManagementPlugins()
if err != nil {
return nil, fmt.Errorf("failed to list sidecar plugins from reposerver: %w", err)
return nil, err
}
out := []*settingspkg.Plugin{}
var out []*settingspkg.Plugin
for _, p := range in {
out = append(out, &settingspkg.Plugin{Name: p.Name})

}
if pluginList != nil && len(pluginList.Items) > 0 {
for _, p := range pluginList.Items {
out = append(out, &settingspkg.Plugin{Name: p.Name})

if includeV2Plugins {
closer, client, err := s.repoClient.NewRepoServerClient()
if err != nil {
return nil, fmt.Errorf("error creating repo server client: %w", err)
}
defer ioutil.Close(closer)

pluginList, err := client.ListPlugins(ctx, &empty.Empty{})
if err != nil {
return nil, fmt.Errorf("failed to list sidecar plugins from reposerver: %w", err)
}

if pluginList != nil && len(pluginList.Items) > 0 {
for _, p := range pluginList.Items {
out = append(out, &settingspkg.Plugin{Name: p.Name})
}
}
}

Expand All @@ -189,7 +201,11 @@ func (s *Server) plugins(ctx context.Context) ([]*settingspkg.Plugin, error) {

// AuthFuncOverride disables authentication for settings service
func (s *Server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) {
// this authenticates the user, but ignores any error, so that we have claims populated
ctx, _ = s.authenticator.Authenticate(ctx)
return ctx, nil
ctx, err := s.authenticator.Authenticate(ctx)
if fullMethodName == "/cluster.SettingsService/Get" {
// SettingsService/Get API is used by login page.
// This authenticates the user, but ignores any error, so that we have claims populated
err = nil
}
return ctx, err
}
13 changes: 10 additions & 3 deletions server/settings/settings.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ message GoogleAnalyticsConfig {
bool anonymizeUsers = 2;
}

message SettingsPluginsResponse {
repeated Plugin plugins = 1;
}

// Help settings
message Help {
// the URL for getting chat help, this will typically be your Slack channel for support
Expand All @@ -64,7 +68,6 @@ message Plugin {
string name = 1;
}


message DexConfig {
repeated Connector connectors = 1;
}
Expand All @@ -88,7 +91,11 @@ service SettingsService {

// Get returns Argo CD settings
rpc Get(SettingsQuery) returns (Settings) {
option (google.api.http).get = "/api/v1/settings";
}
option (google.api.http).get = "/api/v1/settings";
}

// Get returns Argo CD plugins
rpc GetPlugins(SettingsQuery) returns (SettingsPluginsResponse) {
option (google.api.http).get = "/api/v1/settings/plugins";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {FieldApi, FormApi, FormField as ReactFormField, Text, TextArea} from 're

import {ArrayInputField, CheckboxField, EditablePanel, EditablePanelItem, Expandable, TagsInputField} from '../../../shared/components';
import * as models from '../../../shared/models';
import {ApplicationSourceDirectory, AuthSettings} from '../../../shared/models';
import {ApplicationSourceDirectory, Plugin} from '../../../shared/models';
import {services} from '../../../shared/services';
import {ImageTagFieldEditor} from './kustomize';
import * as kustomize from './kustomize-image';
Expand Down Expand Up @@ -258,9 +258,9 @@ export const ApplicationParameters = (props: {
title: 'NAME',
view: source.plugin && source.plugin.name,
edit: (formApi: FormApi) => (
<DataLoader load={() => services.authService.settings()}>
{(settings: AuthSettings) => (
<FormField formApi={formApi} field='spec.source.plugin.name' component={FormSelect} componentProps={{options: (settings.plugins || []).map(p => p.name)}} />
<DataLoader load={() => services.authService.plugins()}>
{(plugins: Plugin[]) => (
<FormField formApi={formApi} field='spec.source.plugin.name' component={FormSelect} componentProps={{options: plugins.map(p => p.name)}} />
)}
</DataLoader>
)
Expand Down
1 change: 0 additions & 1 deletion ui/src/app/shared/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,6 @@ export interface AuthSettings {
chatText: string;
binaryUrls: Record<string, string>;
};
plugins: Plugin[];
userLoginsDisabled: boolean;
kustomizeVersions: string[];
uiCssURL: string;
Expand Down
6 changes: 5 additions & 1 deletion ui/src/app/shared/services/auth-service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
import {AuthSettings} from '../models';
import {AuthSettings, Plugin} from '../models';
import requests from './requests';

export class AuthService {
public settings(): Promise<AuthSettings> {
return requests.get('/settings').then(res => res.body as AuthSettings);
}

public plugins(): Promise<Plugin[]> {
return requests.get('/settings/plugins').then(res => (res.body.plugins || []) as Plugin[]);
}
}