Top Level Namespace
Defined Under Namespace
Classes: State
Instance Method Summary collapse
-
#aur(*names) ⇒ Object
aur command to install packages from aur on install step.
-
#copy(src, dest) ⇒ Object
Copy src inside dest during configure step, if src/.
-
#file(path, content) ⇒ Object
Write a file during configure step.
-
#firewall(*allow) ⇒ Object
setup add ufw enable it and allow ports during configure step.
- #hostname(name) ⇒ Object
-
#keyboard(keymap: nil, layout: nil, model: nil, variant: nil, options: nil) ⇒ Object
set keyboard settings during prepare step.
-
#linux(&block) ⇒ Object
passed block will run in the context of a State instance and then a builder will build this state.
- #locale(value) ⇒ Object
-
#log(msg, args = {}) ⇒ Object
Prints a message to the STDOUT.
-
#package(*names) ⇒ Object
Install a package on install step and remove packages not registered with this function.
-
#replace(file, pattern, replacement) ⇒ Object
Replace a regex pattern with replacement string in a file during configure step.
- #root? ⇒ Boolean
-
#service(*names) ⇒ Object
enable system service if root or user service if not during finalize step.
- #sudo(command) ⇒ Object
-
#timedate(timezone: 'UTC', ntp: true) ⇒ Object
set timezone and NTP settings during prepare step.
-
#timer(*names) ⇒ Object
enable system timer if root or user timer if not during finalize step.
-
#user(name, groups: [], &block) ⇒ Object
create a user and assign a set of group.
Instance Method Details
#aur(*names) ⇒ Object
aur command to install packages from aur on install step
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/declarations.rb', line 43 def aur(*names) names.flatten! @aurs ||= Set.new @aurs += names.map(&:to_s) on_install do names = @aurs || [] log "Install AUR packages", packages: names cache = "./cache/aur" FileUtils.mkdir_p cache Dir.chdir cache do names.each do |package| system("git clone --depth 1 --shallow-submodules https://aur.archlinux.org/#{package}.git") unless Dir.exists?(package) Dir.chdir package do system("makepkg --syncdeps --install --noconfirm --needed") end end end end end |
#copy(src, dest) ⇒ Object
Copy src inside dest during configure step, if src/. will copy src content to dest
180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/declarations.rb', line 180 def copy(src, dest) @copy ||= [] @copy << { src: src, dest: dest } on_configure do next unless @copy next if @copy.empty? @copy.each do |item| log "Copying", item FileUtils.cp_r item[:src], item[:dest] end end end |
#file(path, content) ⇒ Object
Write a file during configure step
223 224 225 226 227 228 229 230 231 232 |
# File 'lib/declarations.rb', line 223 def file(path, content) @files ||= {} @files[path] = content on_configure do @files.each do |path, content| File.write(path, content) end end end |
#firewall(*allow) ⇒ Object
setup add ufw enable it and allow ports during configure step
210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/declarations.rb', line 210 def firewall(*allow) @firewall ||= Set.new @firewall += allow.map(&:to_s) package :ufw service :ufw on_configure do sudo "ufw allow #{@firewall.join(' ')}" end end |
#hostname(name) ⇒ Object
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/declarations.rb', line 234 def hostname(name) @hostname = name file '/etc/hostname', "#{@hostname}\n" on_configure do log "Setting hostname", hostname: @hostname sudo "hostnamectl set-hostname #{@hostname}" end end |
#keyboard(keymap: nil, layout: nil, model: nil, variant: nil, options: nil) ⇒ Object
set keyboard settings during prepare step
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/declarations.rb', line 119 def keyboard(keymap: nil, layout: nil, model: nil, variant: nil, options: nil) @keyboard ||= {} values = { keymap: keymap, layout: layout, model: model, variant: variant, options: }.compact @keyboard.merge!(values) on_prepare do next unless @keyboard[:keymap] sudo "localectl set-keymap #{@keyboard[:keymap]}" m = @keyboard.to_h.slice(:layout, :model, :variant, :options) sudo "localectl set-x11-keymap \"#{m[:layout]}\" \"#{m[:model]}\" \"#{m[:variant]}\" \"#{m[:options]}\"" end end |
#linux(&block) ⇒ Object
passed block will run in the context of a State instance and then a builder will build this state
68 69 70 71 72 |
# File 'lib/core.rb', line 68 def linux(&block) s = State.new s.apply(block) s.run_steps end |
#locale(value) ⇒ Object
140 141 142 143 144 145 146 |
# File 'lib/declarations.rb', line 140 def locale(value) @locale = value on_prepare do sudo "localectl set-locale #{@locale}" end end |
#log(msg, args = {}) ⇒ Object
Prints a message to the STDOUT
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/utils.rb', line 8 def log(msg, args={}) puts msg return unless args.any? max = args.keys.map(&:to_s).max_by(&:length).length args.each do |k, v| vs = case v when Array, Set "(#{v.length}) " + v.join(", ") else v end puts "\t#{k.to_s.rjust(max)}: #{vs}" end end |
#package(*names) ⇒ Object
Install a package on install step and remove packages not registered with this function
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/declarations.rb', line 12 def package(*names) names.flatten! @packages ||= Set.new @packages += names.map(&:to_s) # install step to install packages required and remove not required on_install do # install packages list as is names = @packages.join(" ") log "Installing packages", packages: @packages sudo "pacman --noconfirm --needed -S #{names}" unless @packages.empty? # expand groups to packages group_packages = Set.new(`pacman --quiet -Sg #{names}`.lines.map(&:strip)) # full list of packages that should exist on the system all = @packages + group_packages # actual list on the system installed = Set.new(`pacman -Q --quiet --explicit --unrequired --native`.lines.map(&:strip)) unneeded = installed - all next if unneeded.empty? log "Removing packages", packages: unneeded sudo("pacman -Rs #{unneeded.join(" ")}") end end |
#replace(file, pattern, replacement) ⇒ Object
Replace a regex pattern with replacement string in a file during configure step
196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/declarations.rb', line 196 def replace(file, pattern, replacement) @replace ||= [] @replace << {file: file, pattern: pattern, replacement: replacement} on_configure do @replace.each do |params| input = File.read(params[:file]) output = input.gsub(params[:pattern], params[:replacement]) File.write(params[:file], output) end end end |
#root? ⇒ Boolean
25 26 27 |
# File 'lib/utils.rb', line 25 def root? Process.uid == Etc.getpwnam('root').uid end |
#service(*names) ⇒ Object
enable system service if root or user service if not during finalize step
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/declarations.rb', line 76 def service(*names) names.flatten! @services ||= Set.new @services += names.map(&:to_s) on_finalize do log "Enable services", services: @services user_flags = root? ? "" : "--user" system "systemctl enable #{user_flags} #{@services.join(" ")}" # Disable services that were enabled manually and not in the list we have services = `systemctl list-unit-files #{user_flags} --state=enabled --type=service --no-legend --no-pager` enabled_manually = services.lines.map{|l| l.strip.split(/\s+/) }.select{|l| (l[1] == 'enabled') && (l[2] == 'disabled')} names_without_extension = enabled_manually.map{|l| l.first.delete_suffix(".service") } to_disable = names_without_extension - @services.to_a next if to_disable.empty? log "Services to disable", packages: to_disable # system "systemctl disable #{user_flags} #{to_disable.join(" ")}" end end |
#sudo(command) ⇒ Object
29 30 31 |
# File 'lib/utils.rb', line 29 def sudo(command) root? ? system(command) : system("sudo #{command}") end |
#timedate(timezone: 'UTC', ntp: true) ⇒ Object
set timezone and NTP settings during prepare step
65 66 67 68 69 70 71 72 73 |
# File 'lib/declarations.rb', line 65 def timedate(timezone: 'UTC', ntp: true) @timedate = {timezone: timezone, ntp: ntp} on_configure do log "Set timedate", @timedate sudo "timedatectl set-timezone #{@timedate[:timezone]}" sudo "timedatectl set-ntp #{@timedate[:ntp]}" end end |
#timer(*names) ⇒ Object
enable system timer if root or user timer if not during finalize step
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/declarations.rb', line 101 def timer(*names) names.flatten! @timers ||= Set.new @timers += names.map(&:to_s) on_finalize do log "Enable timers", timers: @timers timers = @timers.map{ |t| "#{t}.timer" }.join(" ") if root? sudo "systemctl enable #{timers}" else system "systemctl enable --user #{timers}" end # disable all other timers end end |
#user(name, groups: [], &block) ⇒ Object
create a user and assign a set of group. if block is passes the block will run in as this user. block will run during the configure step
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/declarations.rb', line 150 def user(name, groups: [], &block) name = name.to_s @user ||= {} @user[name] ||= {} @user[name][:groups] ||= [] @user[name][:groups] += groups.map(&:to_s) @user[name][:state] = State.new @user[name][:state].apply(block) if block_given? on_configure do @user.each do |name, conf| exists = Etc.getpwnam name rescue nil sudo "useradd #{name}" if exists sudo "usermod --groups #{groups.join(",")} #{name}" if groups.any? fork do currentuser = Etc.getpwnam(name) Process::GID.change_privilege(currentuser.gid) Process::UID.change_privilege(currentuser.uid) ENV['XDG_RUNTIME_DIR'] = "/run/user/#{currentuser.uid}" conf[:state].run_steps end Process.wait end end end |