Skip to content

Make opam shared root initialization more robust

This:

  • drops the previous version of the tooling
  • installs the new tooling:
    • use set -e in the main script so command failures are immediately detected by icinga
    • the script triggered by the timer/service script updates all instances at once (in working order, first opam root with the default opam instance, then the other secondary repositories). Implementation wise, it's looping over all instances to init or update them all.
  • also changes the timer period to ~24h (this matches the scheduler configuration for the opam lister)

Related to T3826

Test Plan

*******************************************
- File[/etc/systemd/system/opam-manage-shared-state-coq.inria.fr.service]
*******************************************
  File[/etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer] =>
   parameters =>
     ensure =>
      - file
      + absent
*******************************************
- File[/etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.service]
*******************************************
  File[/etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer] =>
   parameters =>
     ensure =>
      - file
      + absent
*******************************************
- File[/etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.service]
*******************************************
  File[/etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer] =>
   parameters =>
     ensure =>
      - file
      + absent
*******************************************
+ File[/etc/systemd/system/opam-manage-shared-state.service] =>
   parameters =>
      "ensure": "file"
      "group": "root"
      "mode": "0444"
      "notify": "Class[Systemd::Systemctl::Daemon_reload]"
      "owner": "root"
      "show_diff": true
      "content": >>>
# Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state
Requires=network.target
Before=swh-worker@lister.service swh-worker@loader_opam.service
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=oneshot
ExecStart=/usr/local/bin/opam-manage-shared-state.sh

[Install]
WantedBy=swh-worker@lister.service swh-worker@loader_opam.service
<<<
*******************************************
+ File[/etc/systemd/system/opam-manage-shared-state.timer] =>
   parameters =>
      "ensure": "file"
      "group": "root"
      "mode": "0444"
      "notify": ["Class[Systemd::Systemctl::Daemon_reload]", "Service[opam-manage-shared-state.timer]"]
      "owner": "root"
      "show_diff": true
      "content": >>>
[Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
Persistent=true
OnCalendar=daily
RandomizedDelaySec=24h
FixedRandomDelay=true
Unit=.service

[Unit]
Description=Software Heritage Manage OPAM shared state timer
<<<
*******************************************
+ File[/opam-manage-shared-state-coq.inria.fr.service] =>
   parameters =>
      "ensure": "absent"
*******************************************
+ File[/opam-manage-shared-state-ocamlbench-repo.service] =>
   parameters =>
      "ensure": "absent"
*******************************************
+ File[/opam-manage-shared-state-opam.ocaml.org.service] =>
   parameters =>
      "ensure": "absent"
*******************************************
  File[/usr/local/bin/opam-manage-shared-state.sh] =>
   parameters =>
     content =>
      @@ -4,19 +4,50 @@
       # Changes will be overwritten
      _
      -CMD=/usr/bin/opam
      +# This script is in charge of bootstraping the opam root folder with the default opam
      +# repository.
      +
      +set -e
      +
       ROOT_DIR=/tmp/opam/
      -DEFAULT_INSTANCE="opam.ocaml.org"
      -INSTANCE=$1
      -INSTANCE_URL=$2
      -
      -if [ $INSTANCE = $DEFAULT_INSTANCE ]; then
      -  # Opam instance is considered the main instance so we must initialize the repository
      -  # if not present, otherwise we update it
      -  ( $CMD repo --all --root $ROOT_DIR | grep $INSTANCE_URL && $CMD update --root $ROOT_DIR ) \
      -      || $CMD init --reinit --bare --no-setup --root $ROOT_DIR $INSTANCE $INSTANCE_URL
      -else
      -  # Other instances, if present should be updated. If not present, they should be added
      -  # to the main root_dir as extra instances
      -  ( $CMD repo --all --root $ROOT_DIR | grep $INSTANCE_URL && $CMD update --root $ROOT_DIR ) \
      -    || $CMD repository add --root $ROOT_DIR $INSTANCE $INSTANCE_URL
      -fi
      +CMD=/usr/bin/opam
      +
      +function init_or_update_opam_root () {
      +  # Ensure opam root directory exists and references the main opam repository as default
      +  # instance. If not, create it from scratch. If properly configured, update the opam
      +  # repository
      +
      +  instance_name=$1
      +  instance_url=$2
      +
      +  if $CMD repo --all --root $ROOT_DIR | grep -qx $instance_url; then
      +    $CMD update --root $ROOT_DIR
      +  else
      +    $CMD init --reinit --bare --no-setup --root $ROOT_DIR $instance_name $instance_url
      +  fi
      +}
      +
      +function init_or_update_opam_instance () {
      +  # Ensure opam root directory exists and references the main opam repository as default
      +  # instance. If not, create it from scratch. If properly configured, update the opam
      +  # repository.
      +
      +  # Note that This assumes that the function init_or_update_opam_root already got called
      +  # prior to calling this one.
      +
      +  instance_name=$1
      +  instance_url=$2
      +
      +  if $CMD repo --all --root $ROOT_DIR | grep -qx $instance_url; then
      +    $CMD update --root $ROOT_DIR
      +  else
      +    $CMD repository add --root $ROOT_DIR --all-switches $instance_name $instance_url
      +  fi
      +}
      +
      +init_or_update_opam_root opam.ocaml.org https://opam.ocaml.org
      +
      +
      +init_or_update_opam_instance coq.inria.fr https://coq.inria.fr/opam/released
      +
      +init_or_update_opam_instance ocamlbench-repo https://github.com/OCamlPro/ocamlbench-repo.git
      +
*******************************************
  Service[opam-manage-shared-state-coq.inria.fr.timer] =>
   parameters =>
     enable =>
      - true
      + false
*******************************************
  Service[opam-manage-shared-state-ocamlbench-repo.timer] =>
   parameters =>
     enable =>
      - true
      + false
*******************************************
  Service[opam-manage-shared-state-opam.ocaml.org.timer] =>
   parameters =>
     enable =>
      - true
      + false
*******************************************
+ Service[opam-manage-shared-state.timer] =>
   parameters =>
      "enable": true
      "provider": "systemd"
*******************************************
  Systemd::Timer[opam-manage-shared-state-coq.inria.fr.timer] =>
   parameters =>
     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
     service_content =>
      - # Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state (coq.inria.fr)
Requires=network.target
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=simple
ExecStart=/usr/local/bin/opam-manage-shared-state.sh coq.inria.fr https://coq.inria.fr/opam/released

[Install]
WantedBy=multi-user.target

     timer_content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-coq.inria.fr.service

[Unit]
Description=Software Heritage Manage OPAM shared state (coq.inria.fr) timer

*******************************************
  Systemd::Timer[opam-manage-shared-state-ocamlbench-repo.timer] =>
   parameters =>
     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
     service_content =>
      - # Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state (ocamlbench-repo)
Requires=network.target
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=simple
ExecStart=/usr/local/bin/opam-manage-shared-state.sh ocamlbench-repo https://github.com/OCamlPro/ocamlbench-repo.git

[Install]
WantedBy=multi-user.target

     timer_content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-ocamlbench-repo.service

[Unit]
Description=Software Heritage Manage OPAM shared state (ocamlbench-repo) timer

*******************************************
  Systemd::Timer[opam-manage-shared-state-opam.ocaml.org.timer] =>
   parameters =>
     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
     service_content =>
      - # Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state (opam.ocaml.org)
Requires=network.target
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=simple
ExecStart=/usr/local/bin/opam-manage-shared-state.sh opam.ocaml.org https://opam.ocaml.org

[Install]
WantedBy=multi-user.target

     timer_content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-opam.ocaml.org.service

[Unit]
Description=Software Heritage Manage OPAM shared state (opam.ocaml.org) timer

*******************************************
+ Systemd::Timer[opam-manage-shared-state.timer] =>
   parameters =>
      "enable": true
      "ensure": "present"
      "group": "root"
      "mode": "0444"
      "owner": "root"
      "path": "/etc/systemd/system"
      "show_diff": true
      "service_content": >>>
# Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state
Requires=network.target
Before=swh-worker@lister.service swh-worker@loader_opam.service
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=oneshot
ExecStart=/usr/local/bin/opam-manage-shared-state.sh

[Install]
WantedBy=swh-worker@lister.service swh-worker@loader_opam.service
<<<
      "timer_content": >>>
[Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
Persistent=true
OnCalendar=daily
RandomizedDelaySec=24h
FixedRandomDelay=true
Unit=.service

[Unit]
Description=Software Heritage Manage OPAM shared state timer
<<<
*******************************************
- Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.service]
*******************************************
  Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.timer] =>
   parameters =>
     content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-coq.inria.fr.service

[Unit]
Description=Software Heritage Manage OPAM shared state (coq.inria.fr) timer

     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
*******************************************
- Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.service]
*******************************************
  Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.timer] =>
   parameters =>
     content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-ocamlbench-repo.service

[Unit]
Description=Software Heritage Manage OPAM shared state (ocamlbench-repo) timer

     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
*******************************************
- Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.service]
*******************************************
  Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.timer] =>
   parameters =>
     content =>
      - [Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
AccuracySec=4h
Persistent=true
Unit=opam-manage-shared-state-opam.ocaml.org.service

[Unit]
Description=Software Heritage Manage OPAM shared state (opam.ocaml.org) timer

     enable =>
      - true
      + false
     ensure =>
      - present
      + absent
*******************************************
+ Systemd::Unit_file[opam-manage-shared-state.service] =>
   parameters =>
      "ensure": "present"
      "group": "root"
      "mode": "0444"
      "owner": "root"
      "path": "/etc/systemd/system"
      "show_diff": true
      "content": >>>
# Opam manage shared state unit file
# Managed by puppet class profile::swh::deploy::worker::loader_opam
# Changes will be overwritten

[Unit]
Description=Software Heritage Manage OPAM shared state
Requires=network.target
Before=swh-worker@lister.service swh-worker@loader_opam.service
After=network.target

[Service]
User=swhworker
Group=swhworker
Type=oneshot
ExecStart=/usr/local/bin/opam-manage-shared-state.sh

[Install]
WantedBy=swh-worker@lister.service swh-worker@loader_opam.service
<<<
*******************************************
+ Systemd::Unit_file[opam-manage-shared-state.timer] =>
   parameters =>
      "enable": true
      "ensure": "present"
      "group": "root"
      "mode": "0444"
      "owner": "root"
      "path": "/etc/systemd/system"
      "show_diff": true
      "content": >>>
[Install]
WantedBy=timers.target

[Timer]
OnCalendar=daily
Persistent=true
OnCalendar=daily
RandomizedDelaySec=24h
FixedRandomDelay=true
Unit=.service

[Unit]
Description=Software Heritage Manage OPAM shared state timer
<<<
*******************************************
*** End octocatalog-diff on worker01.softwareheritage.org

puppet agent applied freshly (with this):

root@worker01:~# puppet agent --test
Info: Using configured environment 'production'
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Retrieving locales
Info: Loading facts
Info: Caching catalog for worker01.softwareheritage.org
Info: Applying configuration version '1641481571'
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/File[/usr/local/bin/opam-manage-shared-state.sh]/content:
--- /usr/local/bin/opam-manage-shared-state.sh  2022-01-06 15:08:38.499814335 +0000
+++ /tmp/puppet-file20220106-3113-1hqr2sm       2022-01-06 15:08:57.479814335 +0000
@@ -3,20 +3,51 @@
 # Managed by puppet class profile::swh::deploy::worker::loader_opam
 # Changes will be overwritten

-CMD=/usr/bin/opam
+# This script is in charge of bootstraping the opam root folder with the default opam
+# repository.
+
+set -e
+
 ROOT_DIR=/tmp/opam/
-DEFAULT_INSTANCE="opam.ocaml.org"
-INSTANCE=$1
-INSTANCE_URL=$2
-
-if [ $INSTANCE = $DEFAULT_INSTANCE ]; then
-  # Opam instance is considered the main instance so we must initialize the repository
-  # if not present, otherwise we update it
-  ( $CMD repo --all --root $ROOT_DIR | grep $INSTANCE_URL && $CMD update --root $ROOT_DIR ) \
-      || $CMD init --reinit --bare --no-setup --root $ROOT_DIR $INSTANCE $INSTANCE_URL
-else
-  # Other instances, if present should be updated. If not present, they should be added
-  # to the main root_dir as extra instances
-  ( $CMD repo --all --root $ROOT_DIR | grep $INSTANCE_URL && $CMD update --root $ROOT_DIR ) \
-    || $CMD repository add --root $ROOT_DIR $INSTANCE $INSTANCE_URL
-fi
+CMD=/usr/bin/opam
+
+function init_or_update_opam_root () {
+  # Ensure opam root directory exists and references the main opam repository as default
+  # instance. If not, create it from scratch. If properly configured, update the opam
+  # repository
+
+  instance_name=$1
+  instance_url=$2
+
+  if $CMD repo --all --root $ROOT_DIR | grep -qx $instance_url; then
+    $CMD update --root $ROOT_DIR
+  else
+    $CMD init --reinit --bare --no-setup --root $ROOT_DIR $instance_name $instance_url
+  fi
+}
+
+function init_or_update_opam_instance () {
+  # Ensure opam root directory exists and references the main opam repository as default
+  # instance. If not, create it from scratch. If properly configured, update the opam
+  # repository.
+
+  # Note that This assumes that the function init_or_update_opam_root already got called
+  # prior to calling this one.
+
+  instance_name=$1
+  instance_url=$2
+
+  if $CMD repo --all --root $ROOT_DIR | grep -qx $instance_url; then
+    $CMD update --root $ROOT_DIR
+  else
+    $CMD repository add --root $ROOT_DIR --all-switches $instance_name $instance_url
+  fi
+}
+
+init_or_update_opam_root opam.ocaml.org https://opam.ocaml.org
+
+
+init_or_update_opam_instance coq.inria.fr https://coq.inria.fr/opam/released
+
+init_or_update_opam_instance ocamlbench-repo https://github.com/OCamlPro/ocamlbench-repo.git
+

Info: Computing checksum on file /usr/local/bin/opam-manage-shared-state.sh
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/File[/usr/local/bin/opam-manage-shared-state.sh]: Filebucketed /usr/local/bin/opam-manage-shared-state.sh to puppet with sum eddc370058408f8e14f31768f31d7d83
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/File[/usr/local/bin/opam-manage-shared-state.sh]/content: content changed '{md5}eddc370058408f8e14f31768f31d7d83' to '{md5}96e010bcc23be1fa7683c8255b73385e'
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-opam.ocaml.org.timer]/Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.timer]/Service[opam-manage-shared-state-opam.ocaml.org.timer]/enable: enable changed 'true' to 'false'
Info: Computing checksum on file /etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-opam.ocaml.org.timer]/Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.timer]/File[/etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer]: Filebucketed /etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer to puppet with sum e34fc2fbabc002a55062d24c24ea8c90
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-opam.ocaml.org.timer]/Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.timer]/File[/etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer]/ensure: removed
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-opam.ocaml.org.timer]/Systemd::Unit_file[opam-manage-shared-state-opam.ocaml.org.timer]/File[/etc/systemd/system/opam-manage-shared-state-opam.ocaml.org.timer]: Scheduling refresh of Class[Systemd::Systemctl::Daemon_reload]
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-coq.inria.fr.timer]/Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.timer]/Service[opam-manage-shared-state-coq.inria.fr.timer]/enable: enable changed 'true' to 'false'
Info: Computing checksum on file /etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-coq.inria.fr.timer]/Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.timer]/File[/etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer]: Filebucketed /etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer to puppet with sum c2db3f97df8328b934750754d5a20179
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-coq.inria.fr.timer]/Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.timer]/File[/etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer]/ensure: removed
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-coq.inria.fr.timer]/Systemd::Unit_file[opam-manage-shared-state-coq.inria.fr.timer]/File[/etc/systemd/system/opam-manage-shared-state-coq.inria.fr.timer]: Scheduling refresh of Class[Systemd::Systemctl::Daemon_reload]
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-ocamlbench-repo.timer]/Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.timer]/Service[opam-manage-shared-state-ocamlbench-repo.timer]/enable: enable changed 'true' to 'false'
Info: Computing checksum on file /etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-ocamlbench-repo.timer]/Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.timer]/File[/etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer]: Filebucketed /etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer to puppet with sum 2dc9dd69c15b203c685a94c81f11a347
Notice: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-ocamlbench-repo.timer]/Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.timer]/File[/etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer]/ensure: removed
Info: /Stage[main]/Profile::Swh::Deploy::Worker::Loader_opam/Systemd::Timer[opam-manage-shared-state-ocamlbench-repo.timer]/Systemd::Unit_file[opam-manage-shared-state-ocamlbench-repo.timer]/File[/etc/systemd/system/opam-manage-shared-state-ocamlbench-repo.timer]: Scheduling refresh of Class[Systemd::Systemctl::Daemon_reload]
Notice: /Stage[main]/Profile::Systemd_journal::Journalbeat/Service[journalbeat]/ensure: ensure changed 'stopped' to 'running'
Info: /Stage[main]/Profile::Systemd_journal::Journalbeat/Service[journalbeat]: Unscheduling refresh on Service[journalbeat]
Info: Class[Systemd::Systemctl::Daemon_reload]: Scheduling refresh of Exec[systemctl-daemon-reload]
Notice: /Stage[main]/Systemd::Systemctl::Daemon_reload/Exec[systemctl-daemon-reload]: Triggered 'refresh' from 1 event
Notice: Applied catalog in 3.29 seconds

Migrated from D6883 (view on Phabricator)

Merge request reports