picluster/web/images-manage.html
Verita84 48111c89c0 fix
2021-08-25 08:44:55 -06:00

441 lines
15 KiB
HTML

<html>
<head>
<script src="/assets/jquery.min.js"></script>
<link rel="stylesheet" href="/assets/jquery-ui.css">
<script src="/assets/jquery-ui.js"></script>
<link rel="stylesheet" href="/assets/picluster-iframe.css">
<script src="/assets/distLogo.js"></script>
<script src="/assets/dropzone.js"></script>
<script>
function clearAuth() {
document.getElementById('imageauth-user').value = "";
document.getElementById('imageauth-password').value = "";
}
function checkAll(checkbox) {
var checked = checkbox.checked;
var checkboxes = document.getElementsByName('node_list');
checkboxes.forEach(function(e) {
e.checked = checked;
});
}
// Populate container_list drop down
$(function() {
$.get('/listregistries', {
token: parent.token
}, function(data) {
data.forEach(function(e) {
var opt = document.createElement('option');
opt.value = e.name;
opt.innerHTML = e.name;
$('#container_list').append(opt);
});
});
});
$(function() {
$.get("/nodes?token=" + parent.token, function(data) {
/* for (var i in data.nodes) {
option += '<option value="' + data.nodes[i] + '">' + data.nodes[i] + '</option>';
}
option += '<option value="' + '*' + '">' + '*' + '</option>';
$('#image_list_node_options').append(option);
*/
var option = '';
for (var i = 0; i < data.nodes.length; i++) {
option += '<input type="checkbox" name="node_list" checked="checked" value="' + data.nodes[i] + '" /> <label for="node_list">' + data.nodes[i] + '</label><br>';
}
$('#image_list_node_options').append(option);
var selectImage = function(event, ui) {
var image = event.target.value;
var ORIGINAL_TAGS = '<option value="latest" selected="selected">Latest</option>';
if (!image || image.length <= 0) {
remote_tag_name.innerHTML = ORIGINAL_TAGS;
remote_tag_name.disabled = true;
return;
}
// Populate remote_tag_name drop down
$.get('/remoteimagetags', {
token: parent.token,
registry: $('#container_list').val(),
image: $('#image_pull').val(),
username: $('#imageauth-user').val(),
password: $('#imageauth-password').val()
}, function(tags) {
remote_tag_name.innerHTML = ORIGINAL_TAGS;
tags = JSON.parse(tags);
if (tags.results) {
tags.results.forEach(function(e) {
if (e.name.toLowerCase() !== 'latest') {
var opt = document.createElement('option');
opt.value = e.name;
opt.innerHTML = e.name;
remote_tag_name.appendChild(opt);
}
});
} else {
tags.tags.forEach(function(tag) {
if (tag.toLowerCase() !== 'latest') {
var opt = document.createElement('option');
opt.value = tag;
opt.innerHTML = tag;
remote_tag_name.appendChild(opt);
}
});
}
remote_tag_name.disabled = remote_tag_name.children.length > 1 ? false : true;
});
};
// image autocomplete
$("#image_pull").autocomplete({
source: function(request, response) {
$.get('/remoteimages', {
token: parent.token,
registry: $('#container_list').val(),
image: $('#image_pull').val(),
username: $('#imageauth-user').val(),
password: $('#imageauth-password').val()
}, function(images) {
images = JSON.parse(images);
if ($('#container_list').val() === 'hub.docker.com') {
return response(images.results.map(function(e) {
return {
value: e.repo_name,
short_description: e.short_description
};
}));
} else {
return response(images.repositories);
}
});
},
minLength: 2,
change: selectImage,
select: selectImage,
focus: function(event, ui) {
var description = ui.item.short_description || '';
var image_description = document.getElementById('image_description');
image_description.innerHTML = '<hr>' + description;
if (image_description.style.visibility === 'hidden' && description !== '') {
image_description.style.display = 'inline-block';
image_description.style.visibility = 'visible';
image_description.style.margin = 'auto';
image_description.style.padding = 'inherit';
var uiMenu = document.getElementsByClassName('ui-menu') || {};
Object.keys(uiMenu).forEach(function(k) {
// Add some margin to the autocomple menu to account for the
// space taken up by the image description.
uiMenu[k].style.marginTop = '2em';
});
$(image_description).fadeIn();
}
}
});
});
});
$(function() {
// Populate image_list drop down
var option = '';
if (parent.manage_image) {
option += '<option value="' + parent.manage_image + '">' + parent.manage_image + '</option>';
$('#image_list').append(option);
parent.manage_image = '';
} else {
$(function() {
$.get("/nodes?token=" + parent.token, function(data) {
for (var i in data.container_list) {
option += '<option value="' + data.container_list[i] + '">' + data.container_list[i] + '</option>';
}
option += '<option value="' + '*' + '">' + '*' + '</option>';
$('#image_list').append(option);
});
});
}
});
function exec() {
var image_list = document.getElementById("image_list");
var cache = document.getElementById("cache");
var no_cache = 0;
var image_build = image_list.options[image_list.selectedIndex].value;
var image_pull = document.getElementById('image_pull').value;
var registry = document.getElementsByName('container_list')[0].value;
var local_tag_name = document.getElementById('local_tag_name').value;
var remote_tag_name = document.getElementById('remote_tag_name').value;
var radio_image_build = $('input[id=radio_image_build]:checked').val();
var radio_image_delete = $('input[id=radio_image_delete]:checked').val();
var radio_image_pull = $('input[id=radio_image_pull]:checked').val();
var radio_image_upload = $('input[id=radio_start]:checked').val();
var path = '';
var operation = '';
var div = document.getElementById('images-manage-modal-body');
if(cache.checked){
no_cache = 1;
}
if (radio_image_build && image_build) {
div.innerHTML = 'Sent request to the server. Any errors will be reported in this window.<br><br>';
operation = 'build'
$.post('/manage-image', {
token: parent.token,
operation,
container: image_build,
no_cache
}, function(data) {
div.innerHTML = div.innerHTML + data.replace(/(?:\r\n|\r|\n)/g, '<br />');
});
}
if (image_build && radio_image_delete) {
div.innerHTML = 'Sent request to the server. Any errors will be reported in this window.<br><br>';
operation = 'rm'
$.post('/manage-image', {
token: parent.token,
operation,
container: image_build
}, function(data) {
div.innerHTML = div.innerHTML + data.replace(/(?:\r\n|\r|\n)/g, '<br />');
});
}
if (radio_image_pull) {
if (image_pull && local_tag_name) {
// Build the fully qualified image name to pull
image_pull = registry !== 'hub.docker.com' ? registry + '/' + image_pull : 'index.docker.io/' + image_pull;
if (image_pull.indexOf(':') === -1) {
image_pull = remote_tag_name.toLowerCase() !== 'latest' ? image_pull + ':' + remote_tag_name : image_pull;
}
var command = "docker image pull " + image_pull + "; docker tag " + image_pull + ' ' + local_tag_name;
//docker tag tokinring/nginx-php-alpine test
var nodes = document.getElementsByName('node_list');
var div = document.getElementById('images-manage-modal-body');
var username = document.getElementsByName('imageauth-user')[0].value || '';
var password = document.getElementsByName('imageauth-password')[0].value || '';
// Login first if the user has provided authentication
command = username.length > 0 && password.length > 0 ? ["docker", "login", registry, "--username", username, "--password", password].join(' ') + ' && ' + command : command;
var check_counter = 0;
nodes.forEach(function(node, i) {
if (nodes[i].checked) {
nodes.forEach(function(node, i) {
if (nodes[i].checked) {
check_counter++;
$.post('/exec', {
token: parent.token,
command: command,
node: node.value
}, function(data) {});
}
});
}
});
div.innerHTML = check_counter == 0 ? 'Error, no hosts were selected.' : 'Sent request to the server. Please check the logs and running containers for updated information.';
} else {
alert('\nError: Missing local tag name or image name. Please try again');
}
}
}
$(document).ready(function() {
// TODO: Refactor individual radio hide/show into an active/inactive class
$("input[id$='radio_image_build']").click(function() {
$("#image_list_options_fieldset").show();
$(this).is(":checked") ? $("#image_list_build").show() : '';
$(this).is(":checked") ? $("#image_list_build_options").show() : '';
$(this).is(":checked") ? $("#image_list_pull").hide() : '';
$(this).is(":checked") ? $("#image_list_pull_options").hide() : '';
$(this).is(":checked") ? $("#image_description").hide() : '';
$(this).is(":checked") ? $("#image_list_upload").hide() : '';
$(this).is(":checked") ? $("#image_list_options_fieldset").show() : '';
$(this).is(":checked") ? $("#submit_button_div").show() : '';
})
$("input[id$='radio_image_delete']").click(function() {
$("#image_list_options_fieldset").hide();
$(this).is(":checked") ? $("#image_list_build").show() : '';
$(this).is(":checked") ? $("#image_list_pull").hide() : '';
$(this).is(":checked") ? $("#image_list_pull_options").hide() : '';
$(this).is(":checked") ? $("#image_description").hide() : '';
$(this).is(":checked") ? $("#image_list_upload").hide() : '';
$(this).is(":checked") ? $("#submit_button_div").show() : '';
})
$("input[id$='radio_image_pull']").click(function() {
$("#image_list_options_fieldset").show();
$(this).is(":checked") ? $("#image_list_build").hide() : '';
$(this).is(":checked") ? $("#image_list_build_options").hide() : '';
$(this).is(":checked") ? $("#image_list_pull").show() : '';
$(this).is(":checked") ? $("#image_list_pull_options").show() : '';
$(this).is(":checked") ? $("#image_description").show() : '';
$(this).is(":checked") ? $("#image_list_upload").hide() : '';
$(this).is(":checked") ? $("#image_list_options_fieldset").show() : '';
$(this).is(":checked") ? $("#submit_button_div").show() : '';
})
$("input[id$='radio_image_upload']").click(function() {
$("#image_list_options_fieldset").show();
$(this).is(":checked") ? $("#image_list_build").hide() : '';
$(this).is(":checked") ? $("#image_list_build_options").hide() : '';
$(this).is(":checked") ? $("#image_list_pull").hide() : '';
$(this).is(":checked") ? $("#image_list_pull_options").hide() : '';
$(this).is(":checked") ? $("#image_description").hide() : '';
$(this).is(":checked") ? $("#image_list_upload").show() : '';
$(this).is(":checked") ? $("#image_list_options_fieldset").hide() : '';
$(this).is(":checked") ? $("#submit_button_div").hide() : '';
document.getElementById("token").value = parent.token;
})
$("#image_description").hide();
$("#image_list_options_fieldset").hide();
$("#image_list_build").hide();
$("#image_list_build_options").hide();
$("#image_list_pull").hide();
$("#image_list_pull_options").hide();
$("#image_list_upload").hide();
});
</script>
</head>
<body>
<div id="modal_container" class="modal">
<div class="modal-content modal-small">
<div class="modal-header">
<span class="close">&times;</span>
<h2>Manage Images</h2>
</div>
<div class="modal-body">
<fieldset id="image_list_fieldset">
<legend><b>Image</b></legend>
<div id="image_list_action_selector">
<input type="radio" name="image_radio" id="radio_image_build">
<label class="windowfont">Build</label>
<hr>
<input type="radio" name="image_radio" id="radio_image_delete">
<label class="windowfont">Delete</label>
<hr>
<input type="radio" name="image_radio" id="radio_image_pull">
<label class="windowfont">Pull</label>
<hr>
<input type="radio" name="image_radio" id="radio_image_upload">
<label class="windowfont">Upload</label>
</div>
<div id="image_list_build">
<label class="windowfont">Image</label>
<select name="image_list" id="image_list"></select>
</div>
<div id="image_list_pull">
<label for="image_pull">Image</label>
<input id="image_pull"><br>
<label for="remote_tag_name">Remote Tag</label>
<select id="remote_tag_name" disabled="disabled">
<option value="latest" selected="selected">Latest</option>
</select>
<br>
<label for="local_tag_name">Local Tag</label>
<input id="local_tag_name" name="local_tag_name">
<div id="image_description">
<hr>
</div>
</div>
<div id="image_list_upload">
<form id="upload-widget" method="post" action="/upload" class="dropzone">
<input type="hidden" name="token" id="token">
</form>
<hr> The .zip archive will be copied to each node and extracted in the Docker directory.
</div>
</fieldset>
<fieldset id="image_list_options_fieldset">
<legend><b>Options</b></legend>
<div id="image_list_build_options">
<input type="checkbox" id="cache"><label for="image_list">Build without Docker Cache</label>
<br>
</div>
<div id="image_list_pull_options">
<div id="image_list_pull_auth_option">
<legend><b>Authentication</b> <i>(Optional)</i></legend>
<label for="container_list">Registry</label>
<select name="container_list" class="modal_input" id="container_list" onchange="clearAuth()"></select>
<br>
<label for="imageauth-user">Username</label>
<input type="text" name="imageauth-user" id="imageauth-user" class="modal_input" />
<br>
<label for="imageauth-password">Password</label>
<input type="password" name="imageauth-password" id="imageauth-password" class="modal_input" />
</div>
<hr>
<div id="image_list_node_options">
<legend><b>Nodes</b></legend>
<input type="checkbox" name="node_list" onclick="checkAll(this);" checked="checked" />
<label for="node_list">All</label><br>
</div>
</div>
</fieldset>
<div id="submit_button_div">
<button id="submit_button">Submit</button>
</div>
</div>
</div>
</div>
<div id="output" class="modal">
<div class="modal-content modal-large">
<div class="modal-header">
<span class="close">&times;</span>
<h2>Command Output</h2>
</div>
<div id="images-manage-modal-body" class="modal-body">
</div>
</div>
</div>
<script>
var modal = document.getElementById('modal_container');
var span = document.getElementsByClassName("close")[0];
var output_modal = document.getElementById('output');
var output_span = document.getElementsByClassName("close")[1];
var submit_button = document.getElementById("submit_button");
span.onclick = function () {
modal.style.display = "none";
}
output_span.onclick = function () {
output_modal.style.display = "none";
}
submit_button.onclick = function () {
modal.style.display = "none";
output_modal.style.display = "block";
exec();
}
modal.style.display = "block";
</script>
</body>
</html>