Merge branch 'update/1.2.0' into 'master'

Update Minio with Console

See merge request cloudron/minio-app!2
This commit is contained in:
Johannes Zellner 2021-07-20 11:28:26 +00:00
commit e82c8db22d
5 changed files with 139 additions and 109 deletions

View File

@ -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",

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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'));