Merge branch 'update/1.2.0' into 'master'
Update Minio with Console See merge request cloudron/minio-app!2
This commit is contained in:
commit
e82c8db22d
|
@ -5,11 +5,19 @@
|
||||||
"description": "file://DESCRIPTION.md",
|
"description": "file://DESCRIPTION.md",
|
||||||
"changelog": "file://CHANGELOG",
|
"changelog": "file://CHANGELOG",
|
||||||
"tagline": "Distributed object storage",
|
"tagline": "Distributed object storage",
|
||||||
"version": "1.165.1",
|
"version": "2.0.0",
|
||||||
"healthCheckPath": "/minio/login",
|
"healthCheckPath": "/minio/login",
|
||||||
"httpPort": 8000,
|
"httpPort": 8000,
|
||||||
|
"tcpPorts": {
|
||||||
|
"API_PORT": {
|
||||||
|
"title": "API PORT",
|
||||||
|
"description": "API PORT",
|
||||||
|
"defaultValue": 9000
|
||||||
|
}
|
||||||
|
},
|
||||||
"addons": {
|
"addons": {
|
||||||
"localstorage": {}
|
"localstorage": {},
|
||||||
|
"ldap": {}
|
||||||
},
|
},
|
||||||
"manifestVersion": 2,
|
"manifestVersion": 2,
|
||||||
"website": "http://www.minio.io",
|
"website": "http://www.minio.io",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This app packages Minio <upstream>2021-07-08T01-15-01Z</upstream>.
|
This app packages Minio <upstream>2021-07-15T22-27-34Z</upstream>.
|
||||||
|
|
||||||
Minio is a distributed object storage server built for cloud applications and devops.
|
Minio is a distributed object storage server built for cloud applications and devops.
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,11 @@ FROM cloudron/base:3.0.0@sha256:455c70428723e3a823198c57472785437eb6eab082e79b3f
|
||||||
RUN mkdir -p /app/code
|
RUN mkdir -p /app/code
|
||||||
WORKDIR /app/code
|
WORKDIR /app/code
|
||||||
|
|
||||||
ARG VERSION=RELEASE.2021-07-08T01-15-01Z
|
ARG VERSION=RELEASE.2021-07-15T22-27-34Z
|
||||||
|
ARG MC_VERSION=RELEASE.2021-06-13T17-48-22Z
|
||||||
|
|
||||||
RUN wget https://dl.min.io/server/minio/release/linux-amd64/minio.${VERSION} -O /app/code/minio && chmod +x /app/code/minio
|
RUN wget https://dl.min.io/server/minio/release/linux-amd64/minio.${VERSION} -O /app/code/minio && chmod +x /app/code/minio && \
|
||||||
|
wget https://dl.min.io/client/mc/release/linux-amd64/mc.${MC_VERSION} -O /app/code/mc && chmod +x /app/code/mc
|
||||||
|
|
||||||
ADD start.sh /app/code/start.sh
|
ADD start.sh /app/code/start.sh
|
||||||
ADD minio-credentials /app/code/minio-credentials
|
ADD minio-credentials /app/code/minio-credentials
|
||||||
|
|
33
start.sh
33
start.sh
|
@ -9,11 +9,38 @@ mkdir -p /app/data/data /run/minio/config /run/minio/certs
|
||||||
echo "==> Changing ownership"
|
echo "==> Changing ownership"
|
||||||
[[ $(stat --format '%U' /app/data/data) != "cloudron" ]] && chown -R cloudron:cloudron /app/data
|
[[ $(stat --format '%U' /app/data/data) != "cloudron" ]] && chown -R cloudron:cloudron /app/data
|
||||||
|
|
||||||
[[ ! -f /app/data/env.sh ]] && echo -e "# Add custom minio configuration to this file. Restart the app for changes to take effect.\n\nexport CLOUDRON_MINIO_STARTUP_ARGS='server /app/data/data'" > /app/data/env.sh
|
if [[ ! -f /app/data/env.sh ]]; then
|
||||||
|
echo -e "# Add custom minio configuration to this file. Restart the app for changes to take effect.\n\nexport CLOUDRON_MINIO_STARTUP_ARGS='server /app/data/data'" > /app/data/env.sh
|
||||||
|
# https://github.com/minio/minio#things-to-consider
|
||||||
|
echo -e "export MINIO_BROWSER_REDIRECT_URI=$(echo $CLOUDRON_APP_ORIGIN)" >> /app/data/env.sh
|
||||||
|
# ###### ! WARNING ! LDAP IS DISABLED FOR NOW ######
|
||||||
|
# https://github.com/minio/minio/blob/master/docs/sts/ldap.md
|
||||||
|
# https://docs.min.io/minio/baremetal/security/ad-ldap-external-identity-management/configure-ad-ldap-external-identity-management.html#minio-authenticate-using-ad-ldap-generic
|
||||||
|
# (address) AD/LDAP server address e.g. "myldapserver.com:636"
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_SERVER_ADDR='$(echo $CLOUDRON_LDAP_SERVER):$(echo $CLOUDRON_LDAP_PORT)'" >> /app/data/env.sh
|
||||||
|
# (string) DN for LDAP read-only service account used to perform DN and group lookups
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_LOOKUP_BIND_DN='$(echo $CLOUDRON_LDAP_BIND_DN)'" >> /app/data/env.sh
|
||||||
|
# (string) Password for LDAP read-only service account used to perform DN and group lookups
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_LOOKUP_BIND_PASSWORD='$(echo $CLOUDRON_LDAP_BIND_PASSWORD)'" >> /app/data/env.sh
|
||||||
|
# (string) Base LDAP DN to search for user DN
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_USER_DN_SEARCH_BASE_DN='$(echo $CLOUDRON_LDAP_USERS_BASE_DN)'" >> /app/data/env.sh
|
||||||
|
# (string) Search filter to lookup user DN
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_USER_DN_SEARCH_FILTER='(&(objectclass=user)(|(username=%uid)(mail=%uid)))'" >> /app/data/env.sh
|
||||||
|
# https://docs.min.io/minio/baremetal/reference/minio-server/minio-server.html#envvar.MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY='on'" >> /app/data/env.sh
|
||||||
|
# https://docs.min.io/minio/baremetal/reference/minio-server/minio-server.html#envvar.MINIO_IDENTITY_LDAP_TLS_SKIP_VERIFY
|
||||||
|
# echo -e "export MINIO_IDENTITY_LDAP_SERVER_INSECURE='on'" >> /app/data/env.sh
|
||||||
|
# ###### ! WARNING ! LDAP IS DISABLED FOR NOW ######
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d /app/data/mc_config ]]; then
|
||||||
|
echo "==> Set /app/data/mc default config dir"
|
||||||
|
mkdir -p /app/data/mc_config
|
||||||
|
/app/code/mc --config-dir /app/data/mc_config &> /dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
source /app/data/env.sh
|
source /app/data/env.sh
|
||||||
|
|
||||||
# the --config-dir is deprecated and not used. but without it, minio will try to create $HOME/.minio :/ same for --certs-dir
|
# the --config-dir is deprecated and not used. but without it, minio will try to create $HOME/.minio :/ same for --certs-dir
|
||||||
echo "==> Starting minio"
|
echo "==> Starting minio"
|
||||||
exec /usr/local/bin/gosu cloudron:cloudron /app/code/minio --certs-dir /run/minio/certs --config-dir /run/minio/config --quiet ${CLOUDRON_MINIO_STARTUP_ARGS} --address :8000
|
exec /usr/local/bin/gosu cloudron:cloudron /app/code/minio --certs-dir /run/minio/certs --config-dir /run/minio/config --quiet ${CLOUDRON_MINIO_STARTUP_ARGS} --address :$API_PORT --console-address :8000
|
||||||
|
|
||||||
|
|
195
test/test.js
195
test/test.js
|
@ -1,9 +1,11 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
/* jshint esversion: 8 */
|
||||||
/* global describe */
|
/* global describe */
|
||||||
/* global before */
|
/* global before */
|
||||||
/* global after */
|
/* global after */
|
||||||
/* global it */
|
/* global it */
|
||||||
|
/* global xit */
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
@ -15,7 +17,6 @@ var execSync = require('child_process').execSync,
|
||||||
{ Builder, By, Key, until } = require('selenium-webdriver'),
|
{ Builder, By, Key, until } = require('selenium-webdriver'),
|
||||||
{ Options } = require('selenium-webdriver/chrome');
|
{ Options } = require('selenium-webdriver/chrome');
|
||||||
|
|
||||||
|
|
||||||
describe('Application life cycle test', function () {
|
describe('Application life cycle test', function () {
|
||||||
this.timeout(0);
|
this.timeout(0);
|
||||||
|
|
||||||
|
@ -23,130 +24,121 @@ describe('Application life cycle test', function () {
|
||||||
const TEST_TIMEOUT = 10000;
|
const TEST_TIMEOUT = 10000;
|
||||||
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
|
const EXEC_ARGS = { cwd: path.resolve(__dirname, '..'), stdio: 'inherit' };
|
||||||
const BUCKET = 'cloudrontestbucket';
|
const BUCKET = 'cloudrontestbucket';
|
||||||
|
const username = process.env.USERNAME;
|
||||||
|
const password = process.env.PASSWORD;
|
||||||
|
|
||||||
var app;
|
let browser, app;
|
||||||
var browser;
|
|
||||||
|
before(function (done) {
|
||||||
|
if (!process.env.PASSWORD) return done(new Error('PASSWORD env var not set'));
|
||||||
|
if (!process.env.USERNAME) return done(new Error('USERNAME env var not set'));
|
||||||
|
|
||||||
before(function () {
|
|
||||||
browser = new Builder().forBrowser('chrome').setChromeOptions(new Options().windowSize({ width: 1280, height: 1024 })).build();
|
browser = new Builder().forBrowser('chrome').setChromeOptions(new Options().windowSize({ width: 1280, height: 1024 })).build();
|
||||||
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function () {
|
after(function () {
|
||||||
browser.quit();
|
browser.quit();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function sleep(millis) {
|
||||||
|
return new Promise(resolve => setTimeout(resolve, millis));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForElement(elem) {
|
||||||
|
await browser.wait(until.elementLocated(elem), TEST_TIMEOUT);
|
||||||
|
await browser.wait(until.elementIsVisible(browser.findElement(elem)), TEST_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
function getAppInfo() {
|
function getAppInfo() {
|
||||||
var inspect = JSON.parse(execSync('cloudron inspect'));
|
var inspect = JSON.parse(execSync('cloudron inspect'));
|
||||||
app = inspect.apps.filter(function (a) { return a.location.indexOf(LOCATION) === 0; })[0];
|
app = inspect.apps.filter(function (a) { return a.location.indexOf(LOCATION) === 0; })[0];
|
||||||
expect(app).to.be.an('object');
|
expect(app).to.be.an('object');
|
||||||
}
|
}
|
||||||
|
|
||||||
function pageLoaded() {
|
async function login(accessKey='minioadmin', secretKey='minioadmin') {
|
||||||
return browser.wait(until.elementLocated(By.className('page-load pl-0 pl-1')), TEST_TIMEOUT);
|
await browser.get(`https://${app.fqdn}/login`);
|
||||||
|
await waitForElement(By.id('accessKey'));
|
||||||
|
await browser.findElement(By.id('accessKey')).sendKeys(accessKey);
|
||||||
|
await browser.findElement(By.id('secretKey')).sendKeys(secretKey);
|
||||||
|
await browser.findElement(By.xpath('//button[@type="submit"]/span[text()="Login"]')).click();
|
||||||
|
await waitForElement(By.xpath(`//div/span[contains(text(), "Dashboard")]`));
|
||||||
}
|
}
|
||||||
|
|
||||||
function visible(selector) {
|
async function old_login(accessKey='minioadmin', secretKey='minioadmin') {
|
||||||
return browser.wait(until.elementLocated(selector), TEST_TIMEOUT).then(function () {
|
await browser.get(`https://${app.fqdn}/minio/login`);
|
||||||
return browser.wait(until.elementIsVisible(browser.findElement(selector)), TEST_TIMEOUT);
|
await waitForElement(By.id('accessKey'));
|
||||||
});
|
await browser.findElement(By.id('accessKey')).sendKeys(accessKey);
|
||||||
|
await browser.findElement(By.id('secretKey')).sendKeys(secretKey);
|
||||||
|
await browser.findElement(By.xpath('//button[@type="submit"]')).click();
|
||||||
|
await waitForElement(By.xpath(`//input[@placeholder="Search Buckets..."]`));
|
||||||
}
|
}
|
||||||
|
|
||||||
function login(accessKey, secretKey, callback) {
|
async function logout() {
|
||||||
browser.manage().deleteAllCookies();
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
browser.get('https://' + app.fqdn).then(function () {
|
await waitForElement(By.xpath(`//div/span[contains(text(), "Dashboard")]`));
|
||||||
return visible(By.id('accessKey'));
|
await browser.findElement(By.xpath('//div/span[contains(text(), "Logout")]')).click();
|
||||||
}).then(function () {
|
await waitForElement(By.id('accessKey'));
|
||||||
return browser.findElement(By.id('accessKey')).sendKeys(accessKey);
|
|
||||||
}).then(function () {
|
|
||||||
return browser.findElement(By.id('secretKey')).sendKeys(secretKey);
|
|
||||||
}).then(function () {
|
|
||||||
// return browser.findElement(By.className('lw-btn')).click();
|
|
||||||
return browser.findElement(By.tagName('form')).submit();
|
|
||||||
}).then(function () {
|
|
||||||
return browser.wait(until.elementLocated(By.id('top-right-menu')), TEST_TIMEOUT);
|
|
||||||
}).then(function () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function logout(callback) {
|
async function old_logout() {
|
||||||
browser.get('https://' + app.fqdn);
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
|
await waitForElement(By.xpath(`//input[@placeholder="Search Buckets..."]`));
|
||||||
pageLoaded().then(function () {
|
await browser.findElement(By.xpath('//div/button[@id="top-right-menu"]')).click();
|
||||||
return visible(By.id('top-right-menu'));
|
await browser.findElement(By.xpath('//ul/li/a[@id="logout"]')).click();
|
||||||
}).then(function () {
|
await waitForElement(By.id('accessKey'));
|
||||||
return browser.findElement(By.id('top-right-menu')).click();
|
|
||||||
}).then(function () {
|
|
||||||
if (app.manifest.version === '1.137.0') {
|
|
||||||
return visible(By.xpath('//*[text()="Sign Out "]'));
|
|
||||||
} else {
|
|
||||||
return visible(By.xpath('//*[contains(text(), "Logout")]'));
|
|
||||||
}
|
|
||||||
}).then(function () {
|
|
||||||
if (app.manifest.version === '1.137.0') {
|
|
||||||
return browser.findElement(By.xpath('//*[text()="Sign Out "]')).click();
|
|
||||||
} else {
|
|
||||||
return browser.findElement(By.xpath('//*[contains(text(),"Logout")]')).click();
|
|
||||||
}
|
|
||||||
}).then(function () {
|
|
||||||
return browser.wait(until.elementLocated(By.id('accessKey')), TEST_TIMEOUT);
|
|
||||||
}).then(function () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function addBucket(callback) {
|
async function addBucket() {
|
||||||
browser.get('https://' + app.fqdn);
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
|
await waitForElement(By.xpath('//div/span[contains(text(), "Bucket")]'));
|
||||||
pageLoaded().then(function () {
|
await browser.findElement(By.xpath('//div/span[contains(text(), "Bucket")]')).click();
|
||||||
return visible(By.className('fa-plus'));
|
await waitForElement(By.xpath('//span[text()="Create Bucket"]'));
|
||||||
}).then(function () {
|
await browser.findElement(By.xpath('//span[text()="Create Bucket"]')).click();
|
||||||
return browser.findElement(By.className('fa-plus')).click();
|
await browser.findElement(By.xpath('//input[@id="bucket-name"]')).sendKeys(BUCKET);
|
||||||
}).then(function () {
|
await browser.findElement(By.xpath('//button[@type="submit"]/span[text()="Save"]')).click();
|
||||||
const c = 'fa-hdd';
|
await waitForElement(By.xpath(`//div/span[contains(text(), "${BUCKET}")]`));
|
||||||
return visible(By.className(c));
|
await browser.findElement(By.xpath(`//div/span[contains(text(), "${BUCKET}")]`));
|
||||||
}).then(function () {
|
|
||||||
const c = 'fa-hdd';
|
|
||||||
return browser.findElement(By.className(c)).click();
|
|
||||||
}).then(function () {
|
|
||||||
return visible(By.xpath('//*[@class="modal-body"]/form/div/input'));
|
|
||||||
}).then(function () {
|
|
||||||
return browser.findElement(By.xpath('//*[@class="modal-body"]/form/div/input')).sendKeys(BUCKET);
|
|
||||||
}).then(function () {
|
|
||||||
return browser.findElement(By.xpath('//*[@class="modal-body"]/form')).submit();
|
|
||||||
}).then(function () {
|
|
||||||
return visible(By.xpath('//*[@class="main"]/a[text()="' + BUCKET + '"]'));
|
|
||||||
}).then(function () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBucket(callback) {
|
async function old_addBucket() {
|
||||||
browser.get('https://' + app.fqdn);
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
|
await waitForElement(By.xpath(`//input[@placeholder="Search Buckets..."]`));
|
||||||
pageLoaded().then(function () {
|
await browser.findElement(By.xpath('//div/button[@id="fe-action-toggle"]')).click();
|
||||||
return browser.findElement(By.xpath(`//a[contains(text(), ${BUCKET})]`));
|
await browser.findElement(By.xpath('//ul/a[@id="show-make-bucket"]')).click();
|
||||||
}).then(function () {
|
await browser.findElement(By.xpath('//input[@placeholder="Bucket Name"]')).sendKeys(BUCKET);
|
||||||
callback();
|
await browser.findElement(By.xpath('//*[@class="modal-body"]/form')).submit();
|
||||||
});
|
await waitForElement(By.xpath(`//*[@class="main"]/a[text()="${BUCKET}"]`));
|
||||||
}
|
}
|
||||||
|
|
||||||
function openSettings(callback) {
|
async function checkBucket() {
|
||||||
browser.get('https://' + app.fqdn);
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
|
await waitForElement(By.xpath(`//div/span[contains(text(), "Dashboard")]`));
|
||||||
|
await browser.findElement(By.xpath('//div/span[contains(text(), "Bucket")]')).click();
|
||||||
|
await waitForElement(By.xpath(`//div/span[contains(text(), "${BUCKET}")]`));
|
||||||
|
await browser.findElement(By.xpath(`//div/span[contains(text(), "${BUCKET}")]`));
|
||||||
|
}
|
||||||
|
|
||||||
pageLoaded().then(function () {
|
async function old_checkBucket() {
|
||||||
return visible(By.id('top-right-menu'));
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
}).then(function () {
|
await waitForElement(By.xpath(`//input[@placeholder="Search Buckets..."]`));
|
||||||
return browser.findElement(By.id('top-right-menu')).click();
|
await waitForElement(By.xpath(`//*[@class="main"]/a[text()="${BUCKET}"]`));
|
||||||
}).then(function () {
|
}
|
||||||
return visible(By.xpath('//*[contains(text(), "Change Password")]'));
|
|
||||||
}).then(function () {
|
async function openSettings() {
|
||||||
return browser.findElement(By.xpath('//*[contains(text(),"Change Password")]')).click();
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
}).then(function () {
|
await waitForElement(By.xpath(`//div/span[contains(text(), "Dashboard")]`));
|
||||||
return browser.wait(until.elementLocated(By.xpath('//*[contains(text(), "Change Password")]')), TEST_TIMEOUT);
|
await browser.findElement(By.xpath('//div/span[contains(text(), "Account")]')).click();
|
||||||
}).then(function () {
|
await waitForElement(By.xpath(`//button/span[text()="Change Password"]`));
|
||||||
callback();
|
await browser.findElement(By.xpath('//button/span[text()="Change Password"]'));
|
||||||
});
|
}
|
||||||
|
|
||||||
|
async function old_openSettings() {
|
||||||
|
await browser.get(`https://${app.fqdn}/`);
|
||||||
|
await waitForElement(By.xpath(`//input[@placeholder="Search Buckets..."]`));
|
||||||
|
await browser.findElement(By.xpath('//div/button[@id="top-right-menu"]')).click();
|
||||||
|
await waitForElement(By.xpath('//ul/li/a[contains(text(), "Change Password")]'));
|
||||||
|
await browser.findElement(By.xpath('//ul/li/a[contains(text(), "Change Password")]'));
|
||||||
}
|
}
|
||||||
|
|
||||||
xit('build app', function () { execSync('cloudron build', EXEC_ARGS); });
|
xit('build app', function () { execSync('cloudron build', EXEC_ARGS); });
|
||||||
|
@ -199,10 +191,11 @@ describe('Application life cycle test', function () {
|
||||||
it('can install app', function () { execSync('cloudron install --appstore-id io.minio.cloudronapp --location ' + LOCATION, EXEC_ARGS); });
|
it('can install app', function () { execSync('cloudron install --appstore-id io.minio.cloudronapp --location ' + LOCATION, EXEC_ARGS); });
|
||||||
it('can get app information', getAppInfo);
|
it('can get app information', getAppInfo);
|
||||||
|
|
||||||
it('can login', login.bind(null, 'minioadmin', 'minioadmin'));
|
it('can login', old_login.bind(null, 'minioadmin', 'minioadmin'));
|
||||||
it('can add buckets', addBucket);
|
it('can add buckets', old_addBucket);
|
||||||
it('can logout', logout);
|
it('can logout', old_logout);
|
||||||
it('can update', function () { execSync('cloudron update --app ' + LOCATION, EXEC_ARGS); });
|
it('can update', function () { execSync(`cloudron update --app ${LOCATION} --no-wait`, EXEC_ARGS); });
|
||||||
|
it('can enable API Port', function () { execSync(`cloudron configure --app ${LOCATION} -p API_PORT=9000 -l ${LOCATION} `, EXEC_ARGS); });
|
||||||
it('can get app information', getAppInfo);
|
it('can get app information', getAppInfo);
|
||||||
|
|
||||||
it('can login', login.bind(null, 'minioadmin', 'minioadmin'));
|
it('can login', login.bind(null, 'minioadmin', 'minioadmin'));
|
||||||
|
|
Loading…
Reference in New Issue