diff --git a/template/v3/dirs/etc/supervisor/conf.d/supervisord-code-editor.conf b/template/v3/dirs/etc/supervisor/conf.d/supervisord-code-editor.conf index cac5669b..58e187d0 100644 --- a/template/v3/dirs/etc/supervisor/conf.d/supervisord-code-editor.conf +++ b/template/v3/dirs/etc/supervisor/conf.d/supervisord-code-editor.conf @@ -7,5 +7,6 @@ command=start-code-editor autostart=true autorestart=true stdout_logfile=/dev/fd/1 ; Redirect web server logs to stdout +stderr_logfile=/dev/fd/1 stdout_logfile_maxbytes = 0 ; Fix: https://github.com/Supervisor/supervisor/issues/935 stderr_logfile_maxbytes = 0 ; Fix: https://github.com/Supervisor/supervisor/issues/935 diff --git a/template/v3/dirs/usr/local/bin/merge-settings-util.py b/template/v3/dirs/usr/local/bin/merge-settings-util.py new file mode 100644 index 00000000..8b93cae1 --- /dev/null +++ b/template/v3/dirs/usr/local/bin/merge-settings-util.py @@ -0,0 +1,22 @@ +import json +from sys import argv + + +# merges json files file1 and file2, keys in file2 overwriting any keys that already exist in file1 +def main(): + file1, file2 = argv[1], argv[2] + # Read JSON data from files + with open(file1, "r") as f1, open(file2, "r") as f2: + data1 = json.load(f1) + data2 = json.load(f2) + + # Merge the data (simple update) + merged_data = {**data1, **data2} + + # Write the merged data to a new file + with open(file1, "w") as f: + json.dump(merged_data, f) + + +if __name__ == "__main__": + main() diff --git a/template/v3/dirs/usr/local/bin/start-code-editor b/template/v3/dirs/usr/local/bin/start-code-editor index bc97106c..d331ce4f 100755 --- a/template/v3/dirs/usr/local/bin/start-code-editor +++ b/template/v3/dirs/usr/local/bin/start-code-editor @@ -1,6 +1,44 @@ #!/bin/bash set -e +EFS_MOUNT_POINT="/opt/amazon/sagemaker" +EBS_MOUNT_POINT="/home/sagemaker-user" + +persistent_settings_folder="${EBS_MOUNT_POINT}/sagemaker-code-editor-server-data" +default_settings_folder="${EFS_MOUNT_POINT}/sagemaker-code-editor-server-data" + +override_machine_settings() { + # create a new settings file with preset defaults or merge the defaults into the existing settings file + local settings_relative_path="data/Machine" + local settings_file_path_suffix="${settings_relative_path}/settings.json" + local persistent_machine_settings_file="${persistent_settings_folder}/${settings_file_path_suffix}" + local default_machine_settings_file="${default_settings_folder}/${settings_file_path_suffix}" + + if [ ! -f "$persistent_machine_settings_file" ]; then + # copy settings file to EBS if it doesn't exist in EBS + mkdir -p "${persistent_settings_folder}/${settings_relative_path}" + cp "$default_machine_settings_file" "$persistent_machine_settings_file" + echo "Created persistent settings file with default settings at $persistent_machine_settings_file" + else + # if it does exist then merge settings + echo "File already exists: ${persistent_machine_settings_file}. Merging default settings with existing settings." + python3 /usr/local/bin/merge-settings-util.py "$persistent_machine_settings_file" "$default_machine_settings_file" + fi +} + +copy_user_settings() { + local settings_relative_path="data/User" + local settings_file_path_suffix="${settings_relative_path}/settings.json" + local persistent_user_settings_file="${persistent_settings_folder}/${settings_file_path_suffix}" + local default_user_settings_file="${default_settings_folder}/${settings_file_path_suffix}" + if [ ! -f "$persistent_user_settings_file" ]; then + # copy user settings file to EBS if it doesn't exist in EBS + mkdir -p "${persistent_settings_folder}/${settings_relative_path}" + cp "$default_user_settings_file" "$persistent_user_settings_file" + echo "Created persistent settings file with default settings at $persistent_user_settings_file" + fi +} + eval "$(micromamba shell hook --shell=bash)" # Activate conda environment 'base', which is the default environment for sagemaker-distribution @@ -8,12 +46,14 @@ micromamba activate base # Start code-editor server if [ -n "$SAGEMAKER_APP_TYPE_LOWERCASE" ]; then - # SAGEMAKER_APP_TYPE is set, indicating the server is running within a SageMaker - # app. Configure the base url to be `//default`. + # SAGEMAKER_APP_TYPE is set, indicating the server is running within a SageMaker app. + override_machine_settings + copy_user_settings + # Configure the base url to be `//default`. sagemaker-code-editor --host 0.0.0.0 --port 8888 \ --without-connection-token \ --base-path "/$SAGEMAKER_APP_TYPE_LOWERCASE/default" \ - --server-data-dir /opt/amazon/sagemaker/sagemaker-code-editor-server-data \ + --server-data-dir $persistent_settings_folder \ --extensions-dir /opt/amazon/sagemaker/sagemaker-code-editor-server-data/extensions \ --user-data-dir /opt/amazon/sagemaker/sagemaker-code-editor-user-data else