--- /dev/null
+(define-module (infiniteadaptability services cloud-init)
+ #:use-module (gnu packages bash)
+ #:use-module (gnu packages python-web)
+ #:use-module (gnu services)
+ #:use-module (gnu services shepherd)
+ #:use-module (guix gexp)
+ #:use-module (guix records)
+ #:export (cloud-init-configuration cloud-init-service
+ cloud-init-service-type))
+
+(define-record-type* <cloud-init-configuration> cloud-init-configuration
+ make-cloud-init-configuration
+ cloud-init-configuration?
+
+ (cloud-init cloud-init-configuration-cloud-init ;file-like
+ (default python-cloud-init))
+ (init-modules cloud-init-configuration-init-modules ;list of symbols
+ (default '(seed_random growpart
+ resizefs
+ disk_setup
+ mounts
+ set_hostname
+ update_hostname
+ users_groups
+ ssh
+ set_passwords)))
+ (config-modules cloud-init-configuration-config-modules ;list of symbols
+ (default '()))
+ (final-modules cloud-init-configuration-final-modules ;list of symbols
+ (default '(ssh_authkey_fingerprints)))
+ (extra-configuration-files
+ cloud-init-configuration-extra-configuration-files ;list of file-likes
+ (default '())))
+
+(define %cloud-dir
+ "/etc/cloud")
+
+(define %cloud-cfg
+ (string-append %cloud-dir "/cloud.cfg"))
+
+(define %cloud-cfg-d
+ (string-append %cloud-dir "/cloud.cfg.d"))
+
+(define (cloud-init-initialization init-modules config-modules final-modules
+ extra)
+ "Return the gexp to initialize the cloud-init configuration files"
+ #~(begin
+ (use-modules (srfi srfi-1)
+ (srfi srfi-2)
+ (guix build utils))
+
+ (define reduce-modules
+ (lambda (mods)
+ (string-join (map (lambda (mod)
+ (string-append "\n - "
+ (symbol->string mod))) mods))))
+
+ (mkdir-p #$%cloud-cfg-d)
+
+ (unless (null? '(#$@extra))
+ (for-each (lambda (file)
+ (symlink (cadr file)
+ (string-append #$%cloud-cfg-d "/"
+ (car file))))
+ '(#$@extra)))
+
+ (call-with-output-file #$%cloud-cfg
+ (lambda (p)
+ (display "#cloud-config\n" p)
+
+ (unless (null? '(#$@init-modules))
+ (display (string-append "cloud_init_modules:"
+ (reduce-modules '(#$@init-modules)) "\n\n")
+ p))
+ (unless (null? '(#$@config-modules))
+ (display (string-append "cloud_config_modules:"
+ (reduce-modules '(#$@config-modules))
+ "\n\n") p))
+ (unless (null? '(#$@final-modules))
+ (display (string-append "cloud_final_modules:"
+ (reduce-modules '(#$@final-modules))
+ "\n\n") p))))))
+
+(define (cloud-init-activation config)
+ "Return the activation gexp for CONFIG."
+ #~(begin
+ (use-modules (guix build utils))
+ #$(cloud-init-initialization (cloud-init-configuration-init-modules
+ config)
+ (cloud-init-configuration-config-modules
+ config)
+ (cloud-init-configuration-final-modules
+ config)
+ (cloud-init-configuration-extra-configuration-files
+ config))))
+
+(define (cloud-init-service config)
+ "Return a <cloud-init-service> for cloud-init with CONFIG."
+ (define cloud-init
+ (cloud-init-configuration-cloud-init config))
+
+ (define cloud-init-command
+ #~(list (string-append #$(cloud-init-configuration-cloud-init config)
+ "/bin/cloud-init") "--all-stages"))
+
+ (list (shepherd-service (documentation "cloud-init service")
+ (provision '(cloud-init))
+ (requirement '(networking))
+ (one-shot? #t)
+ (start #~(fork+exec-command #$cloud-init-command
+ #:log-file (string-append
+ "/var/log/cloud-init.log")
+ #:environment-variables '
+ ("PATH=/run/current-system/profile/bin:/run/current-system/profile/sbin:"))))))
+
+(define cloud-init-service-type
+ (service-type (name 'cloud-init)
+ (default-value (cloud-init-configuration))
+ (description "cloud init")
+ (extensions (list (service-extension
+ shepherd-root-service-type
+ cloud-init-service)
+ (service-extension activation-service-type
+ cloud-init-activation)))))