configuration/crontab
... ...
@@ -1,3 +1,3 @@
1 1
* * * * * export PATH=/bin:/usr/bin:/usr/local/bin; sleep $(( $RANDOM * 60 / 32768 )); update_authorized_keys_for_landscape_managers_if_changed $( cat /root/ssh-key-reader.token ) https://security-service.sapsailing.com /root 2>&1 >>/var/log/sailing.err
2 2
# NOTICE: Please try to reference the customised crontabs at $GIT_HOME/configuration/crontabs or use
3
-# the build-crontab-and-cp-files script. This file has been maintained for continuity, but is deprecated.
... ...
\ No newline at end of file
0
+# the build_crontab_and_setup_files command in imageupgrade_functions.sh. This file has been maintained for continuity, but is deprecated.
... ...
\ No newline at end of file
configuration/environments_scripts/mongo_instance_setup/README
... ...
@@ -4,8 +4,8 @@ furthermore the ../imageupgrade_functions.sh has to go to /usr/local/bin.
4 4
Deploy mongod.conf to /etc and make sure that /root has a+r and a+x permissions because
5 5
otherwise the mongod user won't be able to read through the symbolic link
6 6
Link mongodb to /etc/logrotate.d
7
-Link the crontab-mongo, in configuration/crontabs/environments, to /root/crontab and run "crontab crontab" as root.
8
-
7
+Utilise the build-crontab-and-cp-files script or the build_crontab_and_setup_files (in imageupgrade_functions.sh)
8
+to create the crontab file and install it in the root user.
9 9
Run with optional EC2 user detail, e.g., as follows:
10 10
11 11
REPLICA_SET_NAME=archive
configuration/mysql_instance_setup/crontab-ec2-user
... ...
@@ -1,3 +1,3 @@
1 1
* * * * * export PATH=/bin:/usr/bin:/usr/local/bin; sleep $(( $RANDOM * 60 / 32768 )); update_authorized_keys_for_landscape_managers_if_changed $( cat /home/ec2-user/ssh-key-reader.token ) https://security-service.sapsailing.com /home/ec2-user
2 2
# NOTICE: Please try to reference the customised crontabs at $GIT_HOME/configuration/crontabs or use
3
-# the build-crontab-and-cp-files script. This file has been maintained for continuity, but is deprecated.
3
+# the build_crontab_and_setup_files command in imageupgrade_functions.sh. This file has been maintained for continuity, but is deprecated.
configuration/sailing_server_setup/crontab-root
... ...
@@ -1,3 +1,3 @@
1 1
* * * * * export PATH=/bin:/usr/bin:/usr/local/bin; sleep $(( $RANDOM * 60 / 32768 )); update_authorized_keys_for_landscape_managers_if_changed $( cat /root/ssh-key-reader.token ) https://security-service.sapsailing.com /root 2>&1 >>/var/log/sailing.err
2 2
# NOTICE: Please try to reference the customised crontabs at $GIT_HOME/configuration/crontabs or use
3
-# the build-crontab-and-cp-files script. This file has been maintained for continuity, but is deprecated.
3
+# the build_crontab_and_setup_files command in imageupgrade_functions.sh. This file has been maintained for continuity, but is deprecated.
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/autoplay/client/nodes/base/AutoPlayNode.java
... ...
@@ -15,6 +15,6 @@ public interface AutoPlayNode {
15 15
* Will be called before onStart, before calling this the default duration is submitted. Override for custom duration.
16 16
* A time can be supplied multiple times, the timer will restart from the time of submission
17 17
*/
18
- default void customDurationHook(Consumer<Integer> consumer) {
18
+ default void customDurationHook(Consumer<Integer> consumerOfDurationInSeconds) {
19 19
};
20 20
}
... ...
\ No newline at end of file
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/AbstractLeaderboardConfigPanel.java
... ...
@@ -117,7 +117,6 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel
117 117
protected SubscriptionServiceFactory subscriptionServiceFactory;
118 118
119 119
private final Displayer<StrippedLeaderboardDTO> leaderboardsDisplayer = new Displayer<StrippedLeaderboardDTO>() {
120
-
121 120
@Override
122 121
public void fill(Iterable<StrippedLeaderboardDTO> result) {
123 122
fillLeaderboards(result);
... ...
@@ -129,7 +128,6 @@ public abstract class AbstractLeaderboardConfigPanel extends FormPanel
129 128
}
130 129
131 130
private final Displayer<RegattaDTO> regattasDisplayer = new Displayer<RegattaDTO>() {
132
-
133 131
@Override
134 132
public void fill(Iterable<RegattaDTO> result) {
135 133
fillRegattas(result);
java/com.sap.sailing.gwt.ui/src/main/java/com/sap/sailing/gwt/ui/adminconsole/LeaderboardConfigPanel.java
... ...
@@ -166,7 +166,6 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel
166 166
stringMessages.createRegattaLeaderboardWithOtherTieBreakingLeaderboard() + " ...",
167 167
leaderboardCreateAndRegattaReadPermission, this::createRegattaLeaderboardWithOtherTieBreakingLeaderboard);
168 168
createRegattaLeaderboardWithOtherTieBreakingLeaderboardBtn.ensureDebugId("CreateRegattaLeaderboardWithOtherTieBreakingLeaderboardButton");
169
-
170 169
leaderboardRemoveButton = buttonPanel.addRemoveAction(stringMessages.remove(), leaderboardSelectionModel, true,
171 170
() -> removeLeaderboards(leaderboardSelectionModel.getSelectedSet()));
172 171
leaderboardRemoveButton.ensureDebugId("LeaderboardsRemoveButton");
... ...
@@ -396,7 +395,7 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel
396 395
397 396
private void editLeaderboard(StrippedLeaderboardDTO leaderboardDTO) {
398 397
final String oldLeaderboardName = leaderboardDTO.getName();
399
- List<StrippedLeaderboardDTO> otherExistingLeaderboard = new ArrayList<StrippedLeaderboardDTO>();
398
+ final List<StrippedLeaderboardDTO> otherExistingLeaderboard = new ArrayList<>();
400 399
otherExistingLeaderboard.addAll(availableLeaderboardList);
401 400
otherExistingLeaderboard.remove(leaderboardDTO);
402 401
if (leaderboardDTO.type.isMetaLeaderboard()) {
... ...
@@ -1113,6 +1112,8 @@ public class LeaderboardConfigPanel extends AbstractLeaderboardConfigPanel
1113 1112
break;
1114 1113
}
1115 1114
}
1115
+ getLeaderboardsRefresher().addIfNotContainedElseReplace(updatedLeaderboard,
1116
+ new NameBasedStrippedLeaderboardDTOEntityIdentityComparator());
1116 1117
availableLeaderboardList.set(indexOfLeaderboard, updatedLeaderboard);
1117 1118
filterLeaderboardPanel.updateAll(availableLeaderboardList);
1118 1119
}
java/com.sap.sse.landscape.aws/src/com/sap/sse/landscape/aws/impl/ApacheReverseProxy.java
... ...
@@ -128,8 +128,9 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
128 128
private void setRedirect(String configFileNameForHostname, String macroName, String hostname,
129 129
Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase, boolean doCommit, boolean doPush, String... macroArguments)
130 130
throws Exception {
131
- String command = "su - " + CONFIG_USER + " -c 'cd " + CONFIG_REPO_PATH + " && git checkout " + CONFIG_REPO_MAIN_BRANCH_NAME + " && echo \"Use " + macroName + " " + hostname + " " + String.join(" ", macroArguments) + "\" > "
132
- + getAbsoluteConfigFilePath(configFileNameForHostname);
131
+ String command = "su - " + CONFIG_USER + " -c 'cd " + CONFIG_REPO_PATH + " && git checkout "
132
+ + CONFIG_REPO_MAIN_BRANCH_NAME + " && echo \"Use " + macroName + " " + hostname + " "
133
+ + String.join(" ", macroArguments) + "\" > " + getAbsoluteConfigFilePath(configFileNameForHostname);
133 134
if (doCommit) {
134 135
command = command + " && cd "
135 136
+ CONFIG_REPO_PATH + " && " + createCommitAndPushString(configFileNameForHostname,
... ...
@@ -145,7 +146,8 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
145 146
}
146 147
147 148
/**
148
- * Overloads {@link #setRedirect(String, String, String, Optional, byte[], boolean, boolean, String...)} and defaults to true and true for committing and pushing.
149
+ * Overloads {@link #setRedirect(String, String, String, Optional, byte[], boolean, boolean, String...)} and
150
+ * defaults to {@code true} and {@code true} for committing and pushing.
149 151
*
150 152
* @see #setRedirect(String, String, String, Optional, byte[], boolean, boolean, String...)
151 153
*/
... ...
@@ -153,10 +155,11 @@ implements com.sap.sse.landscape.Process<RotatingFileBasedLog, MetricsT> {
153 155
Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase, String... macroArguments)
154 156
throws Exception {
155 157
setRedirect(configFileNameForHostname, macroName, hostname, optionalKeyName, privateKeyEncryptionPassphrase,
156
- true, true, macroArguments);
158
+ /* doCommit */ true, /* doPush */ true, macroArguments);
157 159
}
158 160
159
- private String runCommandAndReturnStdoutAndStderr(String command, String stderrLogPrefix, Level stderrLogLevel, Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase) throws Exception {
161
+ private String runCommandAndReturnStdoutAndStderr(String command, String stderrLogPrefix, Level stderrLogLevel,
162
+ Optional<String> optionalKeyName, byte[] privateKeyEncryptionPassphrase) throws Exception {
160 163
final SshCommandChannel sshChannel = getHost().createRootSshChannel(TIMEOUT, optionalKeyName, privateKeyEncryptionPassphrase);
161 164
final String stdout = sshChannel.runCommandAndReturnStdoutAndLogStderr(command, stderrLogPrefix, stderrLogLevel);
162 165
return stdout;
wiki/info/landscape/amazon-ec2.md
... ...
@@ -399,6 +399,56 @@ In the "Amazon Machine Images (AMIs)" table each row offers an action icon for r
399 399
400 400
We now have a script to automatically create a mailing list of all the landscape managers, that is stored in /var/cache. It is updated via a cronjob. We have to be careful to write atomically, so the mailing list isn't missing any email addresses, if the notify-operators script is called midway through a write.
401 401
402
+### Crontab setup and script organisation
403
+
404
+We previously relied on lots of symbolic links to the various architecture scripts, which were scattered throughout the configuration directory of our Git repo. This made it easy to propagate changes, but also led to moments of chaos, as we had to find every single dependency, for every change pushed to the git repo repo (stored by the trac user), in case it was the target of a symbolic link.
405
+
406
+We now have a well defined structure (detailed below) for the different environment types, such as the central reverse proxy, the disposables, the build server, sailing server, etc.. and a method for updating instances in a controlled manner.
407
+```
408
+configuration
409
+├── crontabs
410
+│ ├── crontab-update-trac-trac-urls
411
+│ └── crontab-syncgit
412
+└── environments_scripts
413
+ ├── build-crontab-and-cp-files
414
+ ├── build_server
415
+ │ ├── files
416
+ │ │ ├── etc
417
+ │ │ │ ├── sysconfig
418
+ │ │ │ │ └── hudson
419
+ │ │ │ └── systemd
420
+ │ │ │ └── system
421
+ │ │ . ├── hudson.service
422
+ │ │ . └── mountnvmeswap.service -> ../../../../../repo/etc/systemd/system/mountnvmeswap.service
423
+ │ └── users
424
+ │ └── root
425
+ │ └── crontab-update-authorized-keys -> ../../../../crontabs/crontab-update-authorized-keys
426
+ └── repo
427
+ ├── etc
428
+ └── var
429
+```
430
+In the environments_scripts folder, we have the script `build-crontab-and-cp-files` for the aforementioned "controlled building", which is explained further below. Then we have directories for each environment type as well as a general purpose repo for storing files common to multiple instances. Within each environment type directory, should be a setup script, for creating an instance, of the environment type, from scratch. There is also an optional users and files folder.
431
+
432
+The users folder is for organising crontabs: there is a folder for each user that should have a crontab and, within these username folders, are symbolic links
433
+to the crontabs folder, which contains files named `crontab-"function"`, each one containing a one-line crontab.
434
+
435
+The files folder is for organising files that should reside on the environment type. Within the directory, is a mimicked UNIX filesystem. Files in, say /etc/awstats of reverse_proxy's files dir, should
436
+be found on the reverse proxy instances at /etc/awstats.
437
+
438
+Any scripts common to multiple environment scripts, may be found in the "repo", which is at the same level as the environment types directory, and contains only a mimicked file system (no users folder). These common scripts are added to an environment type, by creating symbolic links from the intended destination on the environment type to the script in the repo. In the example above, the mountnvmeswap.service link indicates the intended location and the contents of the file is the target of the symbolic link.
439
+
440
+The build-crontab-and-cp-files uses this structure to help setup an environment
441
+type. It builds the crontab file, by combining all the referenced crontab
442
+one-liners, storing a copy in the user's home directory and installing it to the specified user. It also copies across the contents of "files" to the corresponding location, de-refencing any symbolic links.
443
+The script should ideally be triggered using a function in `imageupgrade_functions.sh`, titled `build_crontab_and_setup_files`, that takes an environment type (see other arguments below), and temporarily copies (via scp) the environments_scripts folder. It then calls the build-crontab-and-cp-files script.
444
+
445
+This script has a couple of arguments and options. The most important are the arguments.
446
+1. Environment type.
447
+2. User with a checked out Git copy.
448
+3. The relative path within $2 to the Git copy.
449
+Ideally, we would have only a single checked out Git copy across all instances: one on the wiki user of the central. However, some crontabs require references to specific users' files, so we have the strings PATH_OF_GIT_HOME_DIR_TO_REPLACE & PATH_OF_HOME_DIR_TO_REPLACE, in the crontabs, as placeholders for the paths the string itself describes, which the build-crontab-and-cp-files script replaces with the right path.
450
+Have a look at the script itself for more details on the options and arguments.
451
+
402 452
403 453
## Automated SSH Key Management
404 454