Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6531627d4 | ||
|
|
666b09ad3b |
@@ -74,7 +74,7 @@ func initDataStore(dataStorePath string, fileService portainer.FileService) port
|
||||
}
|
||||
|
||||
func initComposeStackManager(assetsPath string, dataStorePath string, reverseTunnelService portainer.ReverseTunnelService, proxyManager *proxy.Manager) portainer.ComposeStackManager {
|
||||
composeWrapper := exec.NewComposeWrapper(assetsPath, proxyManager)
|
||||
composeWrapper := exec.NewComposeWrapper(assetsPath, dataStorePath, proxyManager)
|
||||
if composeWrapper != nil {
|
||||
return composeWrapper
|
||||
}
|
||||
|
||||
@@ -16,17 +16,19 @@ import (
|
||||
// ComposeWrapper is a wrapper for docker-compose binary
|
||||
type ComposeWrapper struct {
|
||||
binaryPath string
|
||||
dataPath string
|
||||
proxyManager *proxy.Manager
|
||||
}
|
||||
|
||||
// NewComposeWrapper returns a docker-compose wrapper if corresponding binary present, otherwise nil
|
||||
func NewComposeWrapper(binaryPath string, proxyManager *proxy.Manager) *ComposeWrapper {
|
||||
func NewComposeWrapper(binaryPath, dataPath string, proxyManager *proxy.Manager) *ComposeWrapper {
|
||||
if !IsBinaryPresent(programPath(binaryPath, "docker-compose")) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &ComposeWrapper{
|
||||
binaryPath: binaryPath,
|
||||
dataPath: dataPath,
|
||||
proxyManager: proxyManager,
|
||||
}
|
||||
}
|
||||
@@ -79,6 +81,8 @@ func (w *ComposeWrapper) command(command []string, stack *portainer.Stack, endpo
|
||||
|
||||
var stderr bytes.Buffer
|
||||
cmd := exec.Command(program, args...)
|
||||
cmd.Env = os.Environ()
|
||||
cmd.Env = append(cmd.Env, fmt.Sprintf("DOCKER_CONFIG=%s", w.dataPath))
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
out, err := cmd.Output()
|
||||
|
||||
@@ -42,7 +42,7 @@ func Test_UpAndDown(t *testing.T) {
|
||||
|
||||
stack, endpoint := setup(t)
|
||||
|
||||
w := NewComposeWrapper("", nil)
|
||||
w := NewComposeWrapper("", "", nil)
|
||||
|
||||
err := w.Up(stack, endpoint)
|
||||
if err != nil {
|
||||
|
||||
@@ -1125,7 +1125,7 @@ type (
|
||||
|
||||
const (
|
||||
// APIVersion is the version number of the Portainer API
|
||||
APIVersion = "2.1.0"
|
||||
APIVersion = "2.1.1"
|
||||
// DBVersion is the version number of the Portainer database
|
||||
DBVersion = 25
|
||||
// ComposeSyntaxMaxVersion is a maximum supported version of the docker compose syntax
|
||||
|
||||
@@ -1,10 +1,32 @@
|
||||
import _ from 'lodash-es';
|
||||
import { KubernetesConfigMap } from 'Kubernetes/models/config-map/models';
|
||||
import { KubernetesConfigMap, KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models';
|
||||
import { KubernetesConfigMapCreatePayload, KubernetesConfigMapUpdatePayload } from 'Kubernetes/models/config-map/payloads';
|
||||
import { KubernetesPortainerConfigurationOwnerLabel } from 'Kubernetes/models/configuration/models';
|
||||
import { KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues';
|
||||
|
||||
class KubernetesConfigMapConverter {
|
||||
static apiToPortainerAccessConfigMap(data) {
|
||||
const res = new KubernetesPortainerAccessConfigMap();
|
||||
res.Id = data.metadata.uid;
|
||||
res.Data = data.data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static createAccessPayload(data) {
|
||||
const res = new KubernetesConfigMapCreatePayload();
|
||||
_.unset(res, 'binaryData');
|
||||
res.metadata.name = data.Name;
|
||||
res.metadata.namespace = data.Namespace;
|
||||
res.data = data.Data;
|
||||
return res;
|
||||
}
|
||||
|
||||
static updateAccessPayload(data) {
|
||||
const res = KubernetesConfigMapConverter.createAccessPayload(data);
|
||||
res.metadata.uid = data.Id;
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* API ConfigMap to front ConfigMap
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,15 @@ export const KubernetesPortainerConfigMapNamespace = 'portainer';
|
||||
export const KubernetesPortainerConfigMapConfigName = 'portainer-config';
|
||||
export const KubernetesPortainerConfigMapAccessKey = 'NamespaceAccessPolicies';
|
||||
|
||||
export function KubernetesPortainerAccessConfigMap() {
|
||||
return {
|
||||
Id: 0,
|
||||
Name: KubernetesPortainerConfigMapConfigName,
|
||||
Namespace: KubernetesPortainerConfigMapNamespace,
|
||||
Data: {},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* ConfigMap Model
|
||||
*/
|
||||
|
||||
@@ -3,6 +3,7 @@ import _ from 'lodash-es';
|
||||
import PortainerError from 'Portainer/error';
|
||||
import KubernetesConfigMapConverter from 'Kubernetes/converters/configMap';
|
||||
import { KubernetesCommonParams } from 'Kubernetes/models/common/params';
|
||||
import { KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models';
|
||||
|
||||
class KubernetesConfigMapService {
|
||||
/* @ngInject */
|
||||
@@ -17,6 +18,54 @@ class KubernetesConfigMapService {
|
||||
this.deleteAsync = this.deleteAsync.bind(this);
|
||||
}
|
||||
|
||||
getAccess(namespace, name) {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const params = new KubernetesCommonParams();
|
||||
params.id = name;
|
||||
const raw = await this.KubernetesConfigMaps(namespace).get(params).$promise;
|
||||
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(raw);
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
return new KubernetesPortainerAccessConfigMap();
|
||||
}
|
||||
throw new PortainerError('Unable to retrieve Portainer accesses', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
createAccess(config) {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
const payload = KubernetesConfigMapConverter.createAccessPayload(config);
|
||||
const params = {};
|
||||
const namespace = payload.metadata.namespace;
|
||||
const data = await this.KubernetesConfigMaps(namespace).create(params, payload).$promise;
|
||||
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data);
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to create Portainer accesses', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
updateAccess(config) {
|
||||
return this.$async(async () => {
|
||||
try {
|
||||
if (!config.Id) {
|
||||
return await this.createAccess(config);
|
||||
}
|
||||
const payload = KubernetesConfigMapConverter.updateAccessPayload(config);
|
||||
const params = new KubernetesCommonParams();
|
||||
params.id = payload.metadata.name;
|
||||
const namespace = payload.metadata.namespace;
|
||||
const data = await this.KubernetesConfigMaps(namespace).update(params, payload).$promise;
|
||||
return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data);
|
||||
} catch (err) {
|
||||
throw new PortainerError('Unable to update Portainer accesses', err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* GET
|
||||
*/
|
||||
@@ -29,12 +78,12 @@ class KubernetesConfigMapService {
|
||||
this.KubernetesConfigMaps(namespace).getYaml(params).$promise,
|
||||
]);
|
||||
|
||||
if (_.get(rawPromise, 'reason.status') == 404 && _.get(yamlPromise, 'reason.status') == 404) {
|
||||
if (_.get(rawPromise, 'reason.status') === 404 && _.get(yamlPromise, 'reason.status') === 404) {
|
||||
return KubernetesConfigMapConverter.defaultConfigMap(namespace, name);
|
||||
}
|
||||
|
||||
// Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get
|
||||
// an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we
|
||||
// Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get
|
||||
// an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we
|
||||
// use response from get() and ignore 500 error as a workaround.
|
||||
if (rawPromise.value) {
|
||||
return KubernetesConfigMapConverter.apiToConfigMap(rawPromise.value, yamlPromise.value);
|
||||
|
||||
@@ -52,7 +52,7 @@ class KubernetesResourcePoolAccessController {
|
||||
let [endpoint, pool, configMap] = await Promise.all([
|
||||
this.EndpointService.endpoint(this.endpointId),
|
||||
this.KubernetesResourcePoolService.get(name),
|
||||
this.KubernetesConfigMapService.get(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName),
|
||||
this.KubernetesConfigMapService.getAccess(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName),
|
||||
]);
|
||||
const group = await this.GroupService.group(endpoint.GroupId);
|
||||
const roles = [];
|
||||
@@ -96,7 +96,7 @@ class KubernetesResourcePoolAccessController {
|
||||
this.state.actionInProgress = true;
|
||||
const newAccesses = _.concat(this.authorizedUsersAndTeams, this.formValues.multiselectOutput);
|
||||
const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses);
|
||||
await this.KubernetesConfigMapService.update(accessConfigMap);
|
||||
await this.KubernetesConfigMapService.updateAccess(accessConfigMap);
|
||||
this.Notifications.success('Access successfully created');
|
||||
this.$state.reload();
|
||||
} catch (err) {
|
||||
@@ -116,7 +116,7 @@ class KubernetesResourcePoolAccessController {
|
||||
this.state.actionInProgress = true;
|
||||
const newAccesses = _.without(this.authorizedUsersAndTeams, ...selectedItems);
|
||||
const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses);
|
||||
await this.KubernetesConfigMapService.update(accessConfigMap);
|
||||
await this.KubernetesConfigMapService.updateAccess(accessConfigMap);
|
||||
this.Notifications.success('Access successfully removed');
|
||||
this.$state.reload();
|
||||
} catch (err) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"author": "Portainer.io",
|
||||
"name": "portainer",
|
||||
"homepage": "http://portainer.io",
|
||||
"version": "2.1.0",
|
||||
"version": "2.1.1",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:portainer/portainer.git"
|
||||
|
||||
Reference in New Issue
Block a user