Skip to content
This repository was archived by the owner on Apr 4, 2026. It is now read-only.

Commit 16e0875

Browse files
committed
Add basic support for compose profiles
1 parent 6e784a9 commit 16e0875

5 files changed

Lines changed: 196 additions & 30 deletions

File tree

source/compose.manager/php/compose_manager_main.php

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@
33
require_once("/usr/local/emhttp/plugins/compose.manager/php/defines.php");
44
require_once("/usr/local/emhttp/plugins/compose.manager/php/util.php");
55

6+
function createComboButton($text, $id, $onClick, $onClickParams, $items) {
7+
$o = "";
8+
9+
$o .= "<div class='combo-btn-group'>";
10+
$o .= "<input type='button' value='$text' class='combo-btn-group-left' id='$id-left-btn' onclick='$onClick($onClickParams);'>";
11+
$o .= "<section class='combo-btn-subgroup dropdown'>";
12+
$o .= "<button type='button' class='dropdown-toggle combo-btn-group-right' data-toggle='dropdown'><i class='fa fa-caret-down'></i></button>";
13+
$o .= "<div class='dropdown-content'>";
14+
foreach ( $items as $item )
15+
{
16+
$o .= "<a href='#' onclick='$onClick($onClickParams, &quot;$item&quot;);'>$item</a>";
17+
}
18+
$o .= "</div>";
19+
$o .= "</section>";
20+
$o .= "</div>";
21+
22+
return $o;
23+
}
24+
625
$vars = parse_ini_file("/var/local/emhttp/var.ini");
726

827
$stackstate = shell_exec($plugin_root."/scripts/compose.sh -c list");
@@ -69,6 +88,12 @@
6988
}
7089
}
7190

91+
$profiles = array();
92+
if ( is_file("$compose_root/$project/profiles") ) {
93+
$profilestext = @file_get_contents("$compose_root/$project/profiles");
94+
$profiles = json_decode($profilestext, false);
95+
}
96+
7297
$o .= "<tr><td width='30%' style='text-align:initial'>";
7398
$o .= "<font size='2'><span class='ca_nameEdit' id='name$id' data-nameName='$projectName' data-isup='$isup' data-scriptName=".escapeshellarg($project)." style='font-size:1.9rem;cursor:pointer;color:#ff8c2f;'><i class='fa fa-gear'></i></span>&nbsp;&nbsp;<b><span style='color:#ff8c2f;'>$projectName</span>&nbsp;</b></font>";
7499
if ( $isup ) {
@@ -97,10 +122,28 @@
97122
$o .= "<span class='ca_descEdit' data-scriptName=".escapeshellarg($project)." id='desc$id'>$description</span>";
98123
$o .= "</td>";
99124
$o .= "<td width=25%></td>";
100-
$o .= "<td width=5%><input type='button' value='Compose Up' class='up$id' id='$id' onclick='ComposeUp(&quot;$compose_root/$project&quot;);'></td>";
101-
$o .= "<td width=5%><input type='button' value='Compose Down' class='down$id' id='$id' onclick='ComposeDown(&quot;$compose_root/$project&quot;);'></td>";
102-
$o .= "<td width=5%><input type='button' value='Update Stack' class='update$id' id='$id' onclick='UpdateStack(&quot;$compose_root/$project&quot;);'></td>";
103-
$o .= "<td width=5%><input type='checkbox' class='auto_start' data-scriptName=".escapeshellarg($project)." id='$id' style='display:none' $autostart></td>";
125+
$buttons = [
126+
["Compose Up", "ComposeUp", "up"],
127+
["Compose Down", "ComposeDown", "down"],
128+
["Update Stack", "UpdateStack", "update"]
129+
];
130+
131+
foreach ($buttons as $button)
132+
{
133+
$o .= "<td width=5%>";
134+
if ( $profiles ) {
135+
// $onclick = $button[1];
136+
$onClickParams = "&quot;$compose_root/$project&quot;";
137+
$o .= createComboButton($button[0], "$button[2]-$id", $button[1], $onClickParams, $profiles);
138+
} else {
139+
$o .= "<input type='button' value='$button[0]' class='$button[2]-button' id='$button[2]-$id' onclick='$button[1](&quot;$compose_root/$project&quot;);'>";
140+
}
141+
$o .= "</td>";
142+
}
143+
144+
$o .= "<td width=5%>";
145+
$o .= "<input type='checkbox' class='auto_start' data-scriptName=".escapeshellarg($project)." id='autostart-$id' style='display:none' $autostart>";
146+
$o .= "</td>";
104147
$o .= "</tr>";
105148
}
106149
?>
@@ -116,6 +159,8 @@
116159
const webui_label = <?php echo json_encode($docker_label_webui); ?>;
117160
const shell_label = <?php echo json_encode($docker_label_shell); ?>;
118161

162+
$('head').append( $('<link rel="stylesheet" type="text/css" />').attr('href', '<?autov("/plugins/compose.manager/styles/comboButton.css");?>') );
163+
119164
if (typeof swal2 === "undefined") {
120165
$('head').append( $('<link rel="stylesheet" type="text/css" />').attr('href', '<?autov("/plugins/compose.manager/styles/sweetalert2.css");?>') );
121166
$.getScript( '/plugins/compose.manager/javascript/sweetalert/sweetalert2.min.js');
@@ -497,6 +542,47 @@ function generateOverride(myID, myProject=null) {
497542
});
498543
}
499544

545+
function generateProfiles(myID, myProject=null) {
546+
var project = myProject;
547+
if( myID ) {
548+
$("#"+myID).tooltipster("close");
549+
project = $("#"+myID).attr("data-scriptname");
550+
}
551+
552+
$.post(caURL,{action:'getYml',script:project},function(rawComposefile) {
553+
var project_profiles = new Set();
554+
if(rawComposefile) {
555+
var rawComposefile = jQuery.parseJSON(rawComposefile);
556+
557+
if( (rawComposefile.result == 'success') ) {
558+
var main_doc = jsyaml.load(rawComposefile.content);
559+
560+
for( var service_key in main_doc.services ) {
561+
var service = main_doc.services[service_key];
562+
if( service.hasOwnProperty("profiles") ) {
563+
// console.log(service.profiles);
564+
for( const profile of service.profiles ) {
565+
project_profiles.add(profile);
566+
}
567+
}
568+
}
569+
570+
// console.log(project_profiles);
571+
var rawProfiles = JSON.stringify(Array.from(project_profiles));
572+
// console.log(rawProfiles);
573+
$.post(caURL,{action:"saveProfiles",script:project,scriptContents:rawProfiles},function(data) {
574+
if (!data) {
575+
swal2({
576+
title: "Failed to update profiles.",
577+
icon: "error",
578+
})
579+
}
580+
});
581+
}
582+
}
583+
});
584+
}
585+
500586
function editComposeFile(myID) {
501587
var origID = myID;
502588
$("#"+myID).tooltipster("close");
@@ -568,6 +654,7 @@ function saveEdit() {
568654
$(".editing").hide();
569655
if (actionStr == 'saveYml') {
570656
generateOverride(null,project);
657+
generateProfiles(null,project);
571658
}
572659
}
573660
});
@@ -621,33 +708,33 @@ function editStackSettings(myID) {
621708
});
622709
}
623710

624-
function ComposeUp(path) {
711+
function ComposeUp(path, profile="") {
625712
var height = 800;
626713
var width = 1200;
627714

628-
$.post(compURL,{action:'composeUp',path:path},function(data) {
715+
$.post(compURL,{action:'composeUp',path:path,profile:profile},function(data) {
629716
if (data) {
630717
openBox(data,"Stack "+basename(path)+" Up",height,width,true);
631718
}
632719
})
633720
}
634721

635-
function ComposeDown(path) {
722+
function ComposeDown(path, profile="") {
636723
var height = 800;
637724
var width = 1200;
638725

639-
$.post(compURL,{action:'composeDown',path:path},function(data) {
726+
$.post(compURL,{action:'composeDown',path:path,profile:profile},function(data) {
640727
if (data) {
641728
openBox(data,"Stack "+basename(path)+" Down",height,width,true);
642729
}
643730
})
644731
}
645732

646-
function UpdateStack(path) {
733+
function UpdateStack(path, profile="") {
647734
var height = 800;
648735
var width = 1200;
649736

650-
$.post(compURL,{action:'composeUpPullBuild',path:path},function(data) {
737+
$.post(compURL,{action:'composeUpPullBuild',path:path,profile:profile},function(data) {
651738
if (data) {
652739
openBox(data,"Update Stack "+basename(path),height,width,true);
653740
}

source/compose.manager/php/compose_util.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function echoComposeCommand($action)
3232
$cfg = parse_plugin_cfg($sName);
3333
$debug = $cfg['DEBUG_TO_LOG'] == "true";
3434
$path = isset($_POST['path']) ? urldecode(($_POST['path'])) : "";
35+
$profile = isset($_POST['profile']) ? urldecode(($_POST['profile'])) : "";
3536
$unRaidVars = parse_ini_file("/var/local/emhttp/var.ini");
3637
if ($unRaidVars['mdState'] != "STARTED" ) {
3738
echo $plugin_root."/scripts/arrayNotStarted.sh";
@@ -75,6 +76,11 @@ function echoComposeCommand($action)
7576
$composeCommand[] = $envPath;
7677
}
7778

79+
if( $profile ) {
80+
$profile = "-g $profile";
81+
$composeCommand[] = $profile;
82+
}
83+
7884
if( $debug ) {
7985
$composeCommand[] = "--debug";
8086
}

source/compose.manager/php/exec.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,24 @@ function getElement($element) {
210210
}
211211
echo json_encode( [ 'result' => 'success', 'fileName' => "$fileName", 'content' => $fileContents ] );
212212
break;
213+
case 'saveProfiles':
214+
$script = isset($_POST['script']) ? urldecode(($_POST['script'])) : "";
215+
$scriptContents = isset($_POST['scriptContents']) ? $_POST['scriptContents'] : "";
216+
$basePath = "$compose_root/$script";
217+
$fileName = "$basePath/profiles";
213218

219+
if( $scriptContents == "[]" ) {
220+
if ( is_file($fileName) ) {
221+
exec("rm ".escapeshellarg($fileName));
222+
echo "$fileName deleted";
223+
}
224+
225+
break;
226+
}
227+
228+
file_put_contents("$fileName",$scriptContents);
229+
echo "$fileName saved";
230+
break;
214231
}
215232

216233
?>

source/compose.manager/scripts/compose.sh

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
#!/bin/bash
22
export HOME=/root
33

4-
SHORT=e:,c:,f:,p:,d:,o:
5-
LONG=env,command:,file:,project_name:,project_dir:,override:,debug,recreate
4+
SHORT=e:,c:,f:,p:,d:,o:,g:
5+
LONG=env,command:,file:,project_name:,project_dir:,override:,profile:,debug,recreate
66
OPTS=$(getopt -a -n compose --options $SHORT --longoptions $LONG -- "$@")
77

88
eval set -- "$OPTS"
99

1010
envFile=""
1111
files=""
1212
project_dir=""
13-
other_options=""
13+
options=""
14+
command_options=""
1415
debug=false
1516

1617
while :
@@ -49,8 +50,12 @@ do
4950
fi
5051
shift 2
5152
;;
53+
-g | --profile )
54+
options="${options} --profile $2"
55+
shift 2
56+
;;
5257
--recreate )
53-
other_options="--force-recreate"
58+
command_options="${command_options} --force-recreate"
5459
shift;
5560
;;
5661
--debug )
@@ -71,27 +76,27 @@ case $command in
7176

7277
up)
7378
if [ "$debug" = true ]; then
74-
logger "docker compose $envFile $files -p "$name" up $other_options -d"
79+
logger "docker compose $envFile $files $options -p "$name" up $command_options -d"
7580
fi
76-
eval docker compose $envFile $files -p "$name" up $other_options -d 2>&1
81+
eval docker compose $envFile $files $options -p "$name" up $command_options -d 2>&1
7782
;;
7883

7984
down)
8085
if [ "$debug" = true ]; then
81-
logger "docker compose $envFile $files -p "$name" down"
86+
logger "docker compose $envFile $files $options -p "$name" down"
8287
fi
83-
eval docker compose $envFile $files -p "$name" down 2>&1
88+
eval docker compose $envFile $files $options -p "$name" down 2>&1
8489
;;
8590

8691
update)
8792
if [ "$debug" = true ]; then
88-
logger "docker compose $envFile $files -p "$name" images -q"
89-
logger "docker compose $envFile $files -p "$name" pull"
90-
logger "docker compose $envFile $files -p "$name" up -d --build"
93+
logger "docker compose $envFile $files $options -p "$name" images -q"
94+
logger "docker compose $envFile $files $options -p "$name" pull"
95+
logger "docker compose $envFile $files $options -p "$name" up -d --build"
9196
fi
9297

9398
images=()
94-
images+=( $(docker compose $envFile $files -p "$name" images -q) )
99+
images+=( $(docker compose $envFile $files $options -p "$name" images -q) )
95100

96101
if [ ${#images[@]} -eq 0 ]; then
97102
delete="-f"
@@ -108,11 +113,11 @@ case $command in
108113
images=( ${images[*]##sha256:} )
109114
fi
110115

111-
eval docker compose $envFile $files -p "$name" pull 2>&1
112-
eval docker compose $envFile $files -p "$name" up -d --build 2>&1
113-
# eval docker compose $envFile $files -p "$name" up -d --build 2>&1
116+
eval docker compose $envFile $files $options -p "$name" pull 2>&1
117+
eval docker compose $envFile $files $options -p "$name" up -d --build 2>&1
118+
# eval docker compose $envFile $files $options -p "$name" up -d --build 2>&1
114119

115-
new_images=( $(docker compose $envFile $files -p "$name" images -q) )
120+
new_images=( $(docker compose $envFile $files $options -p "$name" images -q) )
116121
for target in "${new_images[@]}"; do
117122
for i in "${!images[@]}"; do
118123
if [[ ${images[i]} = $target ]]; then
@@ -131,9 +136,9 @@ case $command in
131136

132137
stop)
133138
if [ "$debug" = true ]; then
134-
logger "docker compose $envFile $files -p "$name" stop"
139+
logger "docker compose $envFile $files $options -p "$name" stop"
135140
fi
136-
eval docker compose $envFile $files -p "$name" stop 2>&1
141+
eval docker compose $envFile $files $options -p "$name" stop 2>&1
137142
;;
138143

139144
list)
@@ -145,9 +150,9 @@ case $command in
145150

146151
logs)
147152
if [ "$debug" = true ]; then
148-
logger "docker compose $envFile $files logs -f"
153+
logger "docker compose $envFile $files $options logs -f"
149154
fi
150-
eval docker compose $envFile $files logs -f 2>&1
155+
eval docker compose $envFile $files $options logs -f 2>&1
151156
;;
152157

153158
*)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/* The container <div> - needed to position the dropdown content */
2+
.dropdown {
3+
position: absolute;
4+
display: inline-block;
5+
}
6+
7+
/* Dropdown Content (Hidden by Default) */
8+
.dropdown-content {
9+
display: none;
10+
position: relative;
11+
background-color: #f1f1f1;
12+
min-width: 100px;
13+
/* min-width: auto; */
14+
z-index: 1;
15+
right: 75px;
16+
}
17+
18+
/* Links inside the dropdown */
19+
.dropdown-content a {
20+
color: black;
21+
padding: 12px 16px;
22+
text-decoration: none;
23+
display: block;
24+
}
25+
26+
/* Change color of dropdown links on hover */
27+
.dropdown-content a:hover {background-color: #ddd}
28+
29+
/* Show the dropdown menu on hover */
30+
.dropdown:hover .dropdown-content {
31+
display: block;
32+
}
33+
34+
.combo-btn-group-left {
35+
border-right-style: none !important;
36+
border-top-right-radius: 0 !important;
37+
border-bottom-right-radius: 0 !important;
38+
margin-right: 0 !important;
39+
}
40+
41+
.combo-btn-group-right {
42+
border-left-style: none !important;
43+
border-top-left-radius: 0 !important;
44+
border-bottom-left-radius: 0 !important;
45+
min-width: auto !important;
46+
margin-right: 0 !important;
47+
}
48+
49+
.combo-btn-subgroup {
50+
display: inline;
51+
}

0 commit comments

Comments
 (0)