completely replace script-updates with $ScriptInstallUpdate

This commit is contained in:
Christian Hesse 2020-03-23 12:21:38 +01:00
parent 1282a91f04
commit 5f46ef7635
7 changed files with 142 additions and 145 deletions

View file

@ -19,7 +19,7 @@ procedure please follow [the long way in detail](README.md#the-long-way-in-detai
:error "Something is wrong with your certificates!"; :error "Something is wrong with your certificates!";
} }
/ file remove "letsencrypt.pem"; / file remove "letsencrypt.pem";
:foreach Script in={ "global-config"; "global-config-overlay"; "global-functions"; "script-updates" } do={ :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={
/ system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script) output=user as-value]->"data"); / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script) output=user as-value]->"data");
} }
/ system script { run global-config; run global-config-overlay; run global-functions; } / system script { run global-config; run global-config-overlay; run global-functions; }

View file

@ -85,7 +85,7 @@ crap and a good example how to *not* do it.
Now let's download the main scripts and add them in configuration on the fly. Now let's download the main scripts and add them in configuration on the fly.
[admin@MikroTik] > :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions"; "script-updates" } do={ / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script) output=user as-value]->"data"); } [admin@MikroTik] > :foreach Script in={ "global-config"; "global-config-overlay"; "global-functions" } do={ / system script add name=$Script source=([ / tool fetch check-certificate=yes-without-crl ("https://git.eworm.de/cgit/routeros-scripts/plain/" . $Script) output=user as-value]->"data"); }
The configuration needs to be tweaked for your needs. Make sure not to send The configuration needs to be tweaked for your needs. Make sure not to send
your mails to `mail@example.com`! Edit `global-config-overlay`, copy your mails to `mail@example.com`! Edit `global-config-overlay`, copy
@ -101,11 +101,7 @@ And finally load configuration and functions and add the scheduler.
Updating scripts Updating scripts
---------------- ----------------
To update existing scripts just run `script-updates`. To update existing scripts just run function `$ScriptInstallUpdate`.
[admin@MikroTik] > / system script run script-updates
Calling function `$ScriptInstallUpdate` does the same.
[admin@MikroTik] > $ScriptInstallUpdate [admin@MikroTik] > $ScriptInstallUpdate

View file

@ -6,7 +6,7 @@
# Make sure all configuration properties are up to date and this # Make sure all configuration properties are up to date and this
# value is in sync with value in script 'global-functions'! # value is in sync with value in script 'global-functions'!
:global GlobalConfigVersion 13; :global GlobalConfigVersion 14;
# This is used for DNS and backup file. # This is used for DNS and backup file.
:global Domain "example.com"; :global Domain "example.com";

View file

@ -7,9 +7,9 @@
# Make sure all configuration properties are up to date and this # Make sure all configuration properties are up to date and this
# value is in sync with value in script 'global-functions'! # value is in sync with value in script 'global-functions'!
# Comment or remove to disable change notifications. # Comment or remove to disable change notifications.
:global GlobalConfigVersion 13; :global GlobalConfigVersion 14;
# The global-config script is updated by script-updates, # The global-config script is updated by $ScriptInstallUpdate,
# global-config-overlay becomes an overlay for your changes. # global-config-overlay becomes an overlay for your changes.
:global ScriptUpdatesIgnore { :global ScriptUpdatesIgnore {
"global-config-overlay" "global-config-overlay"

View file

@ -1,7 +1,7 @@
# RouterOS global-config changes # RouterOS global-config changes
# Copyright (c) 2019-2020 Christian Hesse <mail@eworm.de> # Copyright (c) 2019-2020 Christian Hesse <mail@eworm.de>
# Changes for global-config to be added to notification on script-updates # Changes for global-config to be added to notification on script updates
:global GlobalConfigChanges { :global GlobalConfigChanges {
1="moved variables from 'global-config' to 'global-functions' for independence"; 1="moved variables from 'global-config' to 'global-functions' for independence";
2="variable names became CamelCase to work around scripting issues"; 2="variable names became CamelCase to work around scripting issues";
@ -16,4 +16,5 @@
11="introduced function '\$ScriptInstallUpdate' to install new and update existing scripts"; 11="introduced function '\$ScriptInstallUpdate' to install new and update existing scripts";
12="removed '\$ScriptUpdatesConfigChangesIgnore', comment '\$GlobalConfigVersion' in 'global-config-overlay' to disable change notifications"; 12="removed '\$ScriptUpdatesConfigChangesIgnore', comment '\$GlobalConfigVersion' in 'global-config-overlay' to disable change notifications";
13="configuration for script 'bridge-port-to-default' changed with new syntax in comment"; 13="configuration for script 'bridge-port-to-default' changed with new syntax in comment";
14="dropped script 'script-updates', use '\$ScriptInstallUpdate' exclusively!";
}; };

View file

@ -6,7 +6,7 @@
# global functions # global functions
# expected configuration version # expected configuration version
:global ExpectedConfigVersion 13; :global ExpectedConfigVersion 14;
# global variables not to be changed by user # global variables not to be changed by user
:global GlobalFunctionsReady false; :global GlobalFunctionsReady false;
@ -378,13 +378,143 @@
:set ScriptInstallUpdate do={ :set ScriptInstallUpdate do={
:local Scripts [ :toarray $1 ]; :local Scripts [ :toarray $1 ];
:global ExpectedConfigVersion;
:global GlobalConfigVersion;
:global Identity;
:global IDonate;
:global ScriptUpdatesBaseUrl;
:global ScriptUpdatesFetch;
:global ScriptUpdatesIgnore;
:global ScriptUpdatesUrlSuffix;
:global SentConfigChangesNotification;
:global LogPrintExit;
:global SendNotification;
:foreach Script in=$Scripts do={ :foreach Script in=$Scripts do={
:if ([ / system script print count-only where name=$Script ] = 0) do={ :if ([ / system script print count-only where name=$Script ] = 0) do={
:log info ("Adding new script: " . $Script); $LogPrintExit info ("Adding new script: " . $Script) false;
/ system script add name=$Script source="#!rsc"; / system script add name=$Script source="#!rsc";
} }
} }
/ system script run script-updates;
:foreach Script in=[ / system script find where source~"^#!rsc" or source="" ] do={
:local Ignore 0;
:local ScriptVal [ / system script get $Script ];
:local ScriptFile [ / file find where name=("script-updates/" . $ScriptVal->"name") ];
:local SourceNew;
:if ([ :len $ScriptFile ] > 0) do={
:set SourceNew [ / file get $ScriptFile content ];
/ file remove $ScriptFile;
}
:foreach Scheduler in=[ / system scheduler find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
:local SchedulerVal [ / system scheduler get $Scheduler ];
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
$LogPrintExit warning ("Policies differ for script " . $ScriptVal->"name" . \
" and its scheduler " . $SchedulerVal->"name" . "!") false;
}
:if ($SchedulerVal->"name" != "global-scripts" && \
$SchedulerVal->"start-time" = "startup" && \
$SchedulerVal->"interval" = 0s && \
!(($SchedulerVal->"on-event") ~ "\\brun global-wait\\b")) do={
$LogPrintExit warning ("Scheduler " . $SchedulerVal->"name" . " starts on startup, " . \
"without waiting for global-functions. Run 'global-wait' to avoid race conditions!") false;
}
}
:if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={
:foreach IgnoreLoop in=$ScriptUpdatesIgnore do={
:if ($IgnoreLoop = $ScriptVal->"name") do={ :set Ignore 1; }
}
:if ($Ignore = 0) do={
$LogPrintExit debug ("Fetching script from url: " . $ScriptVal->"name") false;
:do {
:local Result [ / tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . $ScriptVal->"name" . $ScriptUpdatesUrlSuffix) \
output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew ($Result->"data");
}
} on-error={
$LogPrintExit warning ("Failed fetching " . $ScriptVal->"name") false;
}
}
}
:if ([ :len $SourceNew ] > 0) do={
:if ([ :pick $SourceNew 0 5 ] = "#!rsc") do={
:if ($SourceNew != $ScriptVal->"source") do={
:local DontRequirePermissions \
($SourceNew~"\n# requires: dont-require-permissions=yes\n");
$LogPrintExit info ("Updating script: " . $ScriptVal->"name") false;
/ system script set owner=($ScriptVal->"name") source=$SourceNew \
dont-require-permissions=$DontRequirePermissions $Script;
:if ($ScriptVal->"name" = "global-config" && \
[ / system script print count-only where name="global-config-overlay" ] > 0) do={
/ system script { run global-config; run global-config-overlay; }
}
:if ($ScriptVal->"name" = "global-functions") do={
/ system script run global-functions;
}
} else={
$LogPrintExit debug ("Script " . $ScriptVal->"name" . " did not change.") false;
}
} else={
$LogPrintExit warning ("Looks like new script " . $ScriptVal->"name" . " is not valid. Ignoring!") false;
}
} else={
$LogPrintExit debug ("No update for script " . $ScriptVal->"name" . ".") false;
}
}
:if ($SentConfigChangesNotification!=$ExpectedConfigVersion && \
$GlobalConfigVersion < $ExpectedConfigVersion) do={
:global GlobalConfigChanges;
:local ChangeLogCode;
:local ConfigScript "global-config";
:if ([ /system script print count-only where name="global-config-overlay" ] > 0) do={
:set ConfigScript "global-config-overlay";
}
:local NotificationMessage ("Current configuration on " . $Identity . \
" is out of date. Please update " . $ConfigScript . ", then increase " . \
"\$GlobalConfigVersion (currently " . $GlobalConfigVersion . \
") to " . $ExpectedConfigVersion . " and re-run " . $ConfigScript . ".");
$LogPrintExit debug ("Fetching changelog.") false;
:do {
:local Result [ / tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix) \
output=user as-value ];
:if ($Result->"status" = "finished") do={
:set ChangeLogCode ($Result->"data");
}
:set NotificationMessage ($NotificationMessage . "\n\nChanges:");
[ :parse $ChangeLogCode ];
:for I from=($GlobalConfigVersion + 1) to=$ExpectedConfigVersion do={
:set NotificationMessage ($NotificationMessage . \
"\n * " . $GlobalConfigChanges->[ :tostr $I ]);
}
:set GlobalConfigChanges;
} on-error={
$LogPrintExit warning ("Failed fetching changes!") false;
:set NotificationMessage ($NotificationMessage . \
"\n\nChanges are not available.");
}
:if ($IDonate != true) do={
:set NotificationMessage ($NotificationMessage . \
"\n\n==== donation hint ====\n" . \
"This project is developed in private spare time and usage is " . \
"free of charge for you. If you like the scripts and think this is " . \
"of value for you or your business please consider a donation:\n" . \
"https://git.eworm.de/cgit/routeros-scripts/about/#donate");
}
$SendNotification "Configuration warning!" $NotificationMessage;
:set SentConfigChangesNotification $ExpectedConfigVersion;
}
} }
# lock script against multiple invocation # lock script against multiple invocation

View file

@ -1,136 +1,6 @@
#!rsc #!rsc
# RouterOS script: script-updates # RouterOS script: script-updates
# Copyright (c) 2013-2020 Christian Hesse <mail@eworm.de>
#
# update installed scripts from file or url
:global ExpectedConfigVersion;
:global GlobalConfigVersion;
:global Identity;
:global IDonate;
:global ScriptUpdatesBaseUrl;
:global ScriptUpdatesFetch;
:global ScriptUpdatesIgnore;
:global ScriptUpdatesUrlSuffix;
:global SentConfigChangesNotification;
:global LogPrintExit; :global LogPrintExit;
:global SendNotification;
:foreach Script in=[ / system script find where source~"^#!rsc" or source="" ] do={ $LogPrintExit warning "This script has been replaced by function '\$ScriptInstallUpdate'." true;
:local Ignore 0;
:local ScriptVal [ / system script get $Script ];
:local ScriptFile [ / file find where name=("script-updates/" . $ScriptVal->"name") ];
:local SourceNew;
:if ([ :len $ScriptFile ] > 0) do={
:set SourceNew [ / file get $ScriptFile content ];
/ file remove $ScriptFile;
}
:foreach Scheduler in=[ / system scheduler find where on-event~("\\b" . $ScriptVal->"name" . "\\b") ] do={
:local SchedulerVal [ / system scheduler get $Scheduler ];
:if ($ScriptVal->"policy" != $SchedulerVal->"policy") do={
$LogPrintExit warning ("Policies differ for script " . $ScriptVal->"name" . \
" and its scheduler " . $SchedulerVal->"name" . "!") false;
}
:if ($SchedulerVal->"name" != "global-scripts" && \
$SchedulerVal->"start-time" = "startup" && \
$SchedulerVal->"interval" = 0s && \
!(($SchedulerVal->"on-event") ~ "\\brun global-wait\\b")) do={
$LogPrintExit warning ("Scheduler " . $SchedulerVal->"name" . " starts on startup, " . \
"without waiting for global-functions. Run 'global-wait' to avoid race conditions!") false;
}
}
:if ([ :len $SourceNew ] = 0 && $ScriptUpdatesFetch = true) do={
:foreach IgnoreLoop in=$ScriptUpdatesIgnore do={
:if ($IgnoreLoop = $ScriptVal->"name") do={ :set Ignore 1; }
}
:if ($Ignore = 0) do={
$LogPrintExit debug ("Fetching script from url: " . $ScriptVal->"name") false;
:do {
:local Result [ / tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . $ScriptVal->"name" . $ScriptUpdatesUrlSuffix) \
output=user as-value ];
:if ($Result->"status" = "finished") do={
:set SourceNew ($Result->"data");
}
} on-error={
$LogPrintExit warning ("Failed fetching " . $ScriptVal->"name") false;
}
}
}
:if ([ :len $SourceNew ] > 0) do={
:if ([ :pick $SourceNew 0 5 ] = "#!rsc") do={
:if ($SourceNew != $ScriptVal->"source") do={
:local DontRequirePermissions \
($SourceNew~"\n# requires: dont-require-permissions=yes\n");
$LogPrintExit info ("Updating script: " . $ScriptVal->"name") false;
/ system script set owner=($ScriptVal->"name") source=$SourceNew \
dont-require-permissions=$DontRequirePermissions $Script;
:if ($ScriptVal->"name" = "global-config" && \
[ / system script print count-only where name="global-config-overlay" ] > 0) do={
/ system script { run global-config; run global-config-overlay; }
}
:if ($ScriptVal->"name" = "global-functions") do={
/ system script run global-functions;
}
} else={
$LogPrintExit debug ("Script " . $ScriptVal->"name" . " did not change.") false;
}
} else={
$LogPrintExit warning ("Looks like new script " . $ScriptVal->"name" . " is not valid. Ignoring!") false;
}
} else={
$LogPrintExit debug ("No update for script " . $ScriptVal->"name" . ".") false;
}
}
:if ($SentConfigChangesNotification!=$ExpectedConfigVersion && \
$GlobalConfigVersion < $ExpectedConfigVersion) do={
:global GlobalConfigChanges;
:local ChangeLogCode;
:local ConfigScript "global-config";
:if ([ /system script print count-only where name="global-config-overlay" ] > 0) do={
:set ConfigScript "global-config-overlay";
}
:local NotificationMessage ("Current configuration on " . $Identity . \
" is out of date. Please update " . $ConfigScript . ", then increase " . \
"\$GlobalConfigVersion (currently " . $GlobalConfigVersion . \
") to " . $ExpectedConfigVersion . " and re-run " . $ConfigScript . ".");
$LogPrintExit debug ("Fetching changelog.") false;
:do {
:local Result [ / tool fetch check-certificate=yes-without-crl \
($ScriptUpdatesBaseUrl . "global-config.changes" . $ScriptUpdatesUrlSuffix) \
output=user as-value ];
:if ($Result->"status" = "finished") do={
:set ChangeLogCode ($Result->"data");
}
:set NotificationMessage ($NotificationMessage . "\n\nChanges:");
[ :parse $ChangeLogCode ];
:for I from=($GlobalConfigVersion + 1) to=$ExpectedConfigVersion do={
:set NotificationMessage ($NotificationMessage . \
"\n * " . $GlobalConfigChanges->[ :tostr $I ]);
}
:set GlobalConfigChanges;
} on-error={
$LogPrintExit warning ("Failed fetching changes!") false;
:set NotificationMessage ($NotificationMessage . \
"\n\nChanges are not available.");
}
:if ($IDonate != true) do={
:set NotificationMessage ($NotificationMessage . \
"\n\n==== donation hint ====\n" . \
"This project is developed in private spare time and usage is " . \
"free of charge for you. If you like the scripts and think this is " . \
"of value for you or your business please consider a donation:\n" . \
"https://git.eworm.de/cgit/routeros-scripts/about/#donate");
}
$SendNotification "Configuration warning!" $NotificationMessage;
:set SentConfigChangesNotification $ExpectedConfigVersion;
}