promotion 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGELOG CHANGED
@@ -1,5 +1,4 @@
1
-
2
- == Version 1.3.0
1
+ == Version 1.3.1
3
2
  - Added generation of newsyslog.conf
4
3
  - Added some more examples into the shell generated by mkdeploy
5
4
  - eliminated ERB, replacing it with plain text generation
@@ -0,0 +1,69 @@
1
+ module Promotion
2
+ module Generator
3
+ module Crontab
4
+
5
+ # The crontab for each user must be deployed using the crontab tool
6
+ def self.generate(specs)
7
+ sym = "Crontab"
8
+ begin
9
+ schedules = {} # keyed on user, value is array of schedule elements
10
+ specs.each { |spec|
11
+ spec.elements.each("/Specification/Crontab/Schedule") { |sched|
12
+ user = sched.attributes["User"]
13
+ schedules[user] = [] unless schedules.has_key?(user)
14
+ schedules[user] << sched
15
+ }
16
+ }
17
+ schedules.each { |user, crontablist|
18
+ generatedContents = self.contents(user, crontablist)
19
+ userCrontab = File.expand_path(user, Folders::Crontabs)
20
+ begin
21
+ tempFilename = user + ".tmp"
22
+ tempFile = File.new(tempFilename, File::WRONLY | File::CREAT | File::TRUNC)
23
+ tempFile.puts(generatedContents)
24
+ # previous cron jobs are *NOT* preserved - the tab is competely generated!
25
+ # otherwise we accumulate the cron-generated warning messages at the top of the file
26
+ ensure
27
+ tempFile.close unless tempFile.nil? || tempFile.closed?
28
+ end
29
+ $log.info("Checking temporary crontab written to #{tempFilename}.")
30
+ crontabResults = `#{Files::Crontab} -u #{user} #{tempFilename}`
31
+ if $?.exitstatus == 0
32
+ $log.info("crontab confirms that crontab syntax is correct for user #{user}.")
33
+ else
34
+ $log.error(crontabResults)
35
+ raise
36
+ end
37
+ FileUtils.rm_f(tempFilename)
38
+ $log.info("New crontab installed for user #{user}")
39
+ }
40
+ rescue => e
41
+ $log.error("Error occurred while generating crontab\n#{e.message}" + e.backtrace.join("\n"))
42
+ exit 1
43
+ end
44
+ end
45
+
46
+ # Generates the contents for /var/cron/tabs/{user}, containing scheduled jobs
47
+ def self.contents(user, crontablist)
48
+ contents = []
49
+ contents << "# /var/cron/tabs/#{user} - #{user}'s crontab \n#\n"
50
+ contents << "#minute hour mday month wday command\n#\n\n"
51
+ crontablist.each { |sched|
52
+ if sched.attributes["Comment"]
53
+ contents << "#______________________________\n"
54
+ contents << "#{sched.attributes["Comment"]} \n"
55
+ end
56
+ minute = sched.attributes["Minute"] || "*"
57
+ hour = sched.attributes["Hour"] || "*"
58
+ mday = sched.attributes["DayOfMonth"] || "*"
59
+ month = sched.attributes["Month"] || "*"
60
+ wday = sched.attributes["DayOfWeek"] || "*"
61
+ cmd = (sched.elements["Command"].cdatas[0]).value().strip()
62
+ contents << minute + "\t" + hour + "\t" + mday + "\t" + month + "\t" + wday + "\t" + cmd + "\n"
63
+ }
64
+ return(contents.join(""))
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,51 @@
1
+ module Promotion
2
+ module Generator
3
+ module Newsyslog
4
+
5
+ # Writes the Newsyslog configuration
6
+ def self.generate(specs)
7
+ sym = "Newsyslog"
8
+ begin
9
+ originalContents = Promotion::Generator::original_contents_for(sym)
10
+ newContents = originalContents + Marker + contents(specs)
11
+ Promotion::Generator::write_file_for(sym, newContents)
12
+ rescue => e
13
+ $log.error("Error occurred while generating #{sym}\n#{e.message}" + e.backtrace.join("\n"))
14
+ exit 1
15
+ end
16
+ end
17
+
18
+ # Generates the contents for /etc/newsyslog.conf, which controls rolling and retention of logs
19
+ def self.contents(specs)
20
+ contents = []
21
+ contents << "# This section of the file should not be edited\n"
22
+ contents << "# It was generated by the promotion application and will be overwritten\n"
23
+ contents << "# when the next promotion occurs.\n"
24
+ contents << "# The previous section will be preserved\n\n"
25
+ contents << "# Filename Owner:Group Mode Count Size When Flags\n"
26
+ specs.each { |spec|
27
+ spec.elements.each("/Specification/Newsyslog") { |nsl|
28
+ contents << "%-40s" % nsl.text()
29
+ owner = nsl.attributes["Owner"]
30
+ group = nsl.attributes["Group"]
31
+ if owner.nil? or group.nil?
32
+ og = ""
33
+ else
34
+ og = owner + ":" + group
35
+ end
36
+ contents << "%-20s" % og
37
+ contents << "%-7s" % (nsl.attributes["Mode"] || "0640")
38
+ contents << "%-7s" % (nsl.attributes["Count"] || "*")
39
+ contents << "%-7s" % (nsl.attributes["Size"] || "*")
40
+ contents << "%-9s" % (nsl.attributes["When"] || "*")
41
+ contents << "Z" if (nsl.attributes["Zip"] || "true") == "true"
42
+ contents << "B" if (nsl.attributes["Binary"] || "false") == "true"
43
+ contents << "\n"
44
+ }
45
+ }
46
+ return(contents.join(""))
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,43 @@
1
+ module Promotion
2
+ module Generator
3
+ module Profile
4
+
5
+ # Writes the system profile
6
+ def self.generate(specs)
7
+ sym = "Profile"
8
+ begin
9
+ originalContents = Promotion::Generator::original_contents_for(sym)
10
+ newContents = originalContents + Marker + contents(specs)
11
+ Promotion::Generator::write_file_for(sym, newContents)
12
+ rescue => e
13
+ $log.error("Error occurred while generating #{sym}\n#{e.message}" + e.backtrace.join("\n"))
14
+ exit 1
15
+ end
16
+ end
17
+
18
+ # Generates the contents for /etc/profile, containing environment variables and aliases
19
+ def self.contents(specs)
20
+ contents = []
21
+ contents << "# This section of the file should not be edited\n"
22
+ contents << "# It was generated by the promotion application and will be overwritten\n"
23
+ contents << "# when the next promotion occurs.\n"
24
+ contents << "# The previous section will be preserved\n"
25
+ specs.each { |spec|
26
+ spec.elements.each("/Specification/Environment") { |env|
27
+ env.elements.each("Variable") { |var|
28
+ t = var.cdatas.length > 0 ? var.cdatas[0].to_s() : var.text()
29
+ contents << "export #{var.attributes["Name"]}=\"#{t}\" \n"
30
+ }
31
+ env.elements.each("Alias") { |ali|
32
+ contents << "# #{ali.attributes["Comment"]}\n" if ali.attributes["Comment"]
33
+ t = ali.cdatas.length > 0 ? ali.cdatas[0].to_s() : ali.text()
34
+ contents << "alias #{ali.attributes["Name"]}='#{t}' \n"
35
+ }
36
+ }
37
+ }
38
+ return(contents.join(""))
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,48 @@
1
+ module Promotion
2
+ module Generator
3
+ module Rcconf
4
+
5
+ # Writes the system file /etc/rc.conf.local
6
+ def self.generate(specs)
7
+ sym = "Rc_conf"
8
+ begin
9
+ originalContents = Promotion::Generator::original_contents_for(sym)
10
+ newContents = originalContents + Marker + contents(specs)
11
+ Promotion::Generator::write_file_for(sym, newContents)
12
+ rescue => e
13
+ $log.error("Error occurred while generating #{sym}\n#{e.message}" + e.backtrace.join("\n"))
14
+ exit 1
15
+ end
16
+ end
17
+
18
+ # Generates the contents for /etc/rc.conf.local, containing instructions for running daemons
19
+ def self.contents(specs)
20
+ contents = []
21
+ contents << "# This section of the file should not be edited\n"
22
+ contents << "# It was generated by the promotion application and will be overwritten\n"
23
+ contents << "# when the next promotion occurs.\n"
24
+ contents << "# The previous section will be preserved\n"
25
+ contents << "# ---------------------------\n"
26
+ contents << "# generated application flags\n"
27
+ daemonSpecs = specs.reject {|s| s.elements["/Specification/Daemon"].nil? }
28
+ daemonSpecs.sort!() { |a, b|
29
+ ap = a.elements["/Specification/Daemon"].attributes["Priority"].to_i || 10
30
+ bp = b.elements["/Specification/Daemon"].attributes["Priority"].to_i || 10
31
+ ap <=> bp
32
+ }
33
+ pkgScripts = []
34
+ daemonSpecs.each { |spec|
35
+ name = spec.attributes["Name"]
36
+ flags = spec.elements["/Specification/Daemon"].attributes["Flags"]
37
+ contents << "#{name}_flags=\"#{flags}\" \n"
38
+ pkgScripts << name
39
+ }
40
+ contents << "# rc.d(8) packages scripts\n"
41
+ contents << "# started in the specified order and stopped in reverse order\n"
42
+ contents << "pkg_scripts=\"#{pkgScripts.join(" ")}\" \n"
43
+ return(contents.join(""))
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,55 @@
1
+ module Promotion
2
+ module Generator
3
+ module Sudoers
4
+
5
+ # Writes the sudoers file after testing it with visudo
6
+ def self.generate(specs)
7
+ sym = "Sudoers"
8
+ begin
9
+ originalContents = Promotion::Generator::original_contents_for(sym)
10
+ newContents = originalContents + Marker + contents(specs)
11
+ tempFilename = Promotion::Generator::write_file_for(sym, newContents, true)
12
+ $log.info("Checking temporary sudoers written to #{tempFilename}.")
13
+ visudoResults = `#{Files::Visudo} -c -f #{tempFilename}`
14
+ if visudoResults =~ /parsed OK/
15
+ $log.info("visudo confirms that sudoers syntax is correct.")
16
+ else
17
+ $log.error(visudoResults)
18
+ raise
19
+ end
20
+ Promotion::Generator::write_file_for("Sudoers", newContents)
21
+ FileUtils.rm_f(tempFilename)
22
+ rescue => e
23
+ $log.error("Error occurred while generating sudoers\n#{e.message}" + e.backtrace.join("\n"))
24
+ exit 1
25
+ end
26
+ end
27
+
28
+ # Generates the contents for /etc/sudoers, containing environment variables and aliases
29
+ def self.contents(specs)
30
+ contents = []
31
+ contents << "# This section of the file should not be edited\n"
32
+ contents << "# It was generated by the promotion application and will be overwritten\n"
33
+ contents << "# when the next promotion occurs.\n"
34
+ contents << "# The previous section will be preserved\n\n"
35
+ contents << "Defaults timestamp_timeout=55\n\n"
36
+ contents << "root ALL = (ALL) ALL \n"
37
+ contents << "# people in group wheel may run all commands \n"
38
+ contents << "%wheel ALL = (ALL) ALL \n\n"
39
+ contents << "# Generated user privilege specifications \n"
40
+ specs.each { |spec|
41
+ spec.elements.each("/Specification/Sudoers/UserPrivilege") { |priv|
42
+ contents << "%-16s" % priv.attributes["User"]
43
+ contents << " ALL = "
44
+ contents << "(#{priv.attributes["Runas"]}) " if priv.attributes["Runas"]
45
+ pwd = (priv.attributes["Password"] || "false").downcase() == "true"
46
+ contents << (pwd ? " " : "NOPASSWD: ")
47
+ contents << "#{priv.text().strip()} \n"
48
+ }
49
+ }
50
+ return(contents.join(""))
51
+ end
52
+
53
+ end
54
+ end
55
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: promotion
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 3
9
- - 0
10
- version: 1.3.0
9
+ - 1
10
+ version: 1.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Richard Kernahan
@@ -65,10 +65,11 @@ files:
65
65
  - lib/promotion/enforcer.rb
66
66
  - lib/promotion/evolver.rb
67
67
  - lib/promotion/generator.rb
68
- - lib/promotion/erb/crontab.erb
69
- - lib/promotion/erb/profile.erb
70
- - lib/promotion/erb/rc.conf.local.erb
71
- - lib/promotion/erb/sudoers.erb
68
+ - lib/promotion/generator/crontab.rb
69
+ - lib/promotion/generator/newsyslog.rb
70
+ - lib/promotion/generator/profile.rb
71
+ - lib/promotion/generator/rcconf.rb
72
+ - lib/promotion/generator/sudoers.rb
72
73
  - .yardopts
73
74
  - promotion.xsd
74
75
  - CHANGELOG
@@ -1,19 +0,0 @@
1
- #
2
- # /var/cron/tabs/<%= user %> - <%= user %>'s crontab
3
- #
4
- #minute hour mday month wday command
5
- #
6
- <% crontablist.each do |sched| %>
7
- <% if sched.attributes["Comment"] %>
8
- #______________________________
9
- # <%= sched.attributes["Comment"] %>
10
- <% end %>
11
- <% minute = sched.attributes["Minute"] || "*" %>
12
- <% hour = sched.attributes["Hour"] || "*" %>
13
- <% mday = sched.attributes["DayOfMonth"] || "*" %>
14
- <% month = sched.attributes["Month"] || "*" %>
15
- <% wday = sched.attributes["DayOfWeek"] || "*" %>
16
- <% cmd = (sched.elements["Command"].cdatas[0]).value().strip() %>
17
- <%= minute + "\t" + hour + "\t" + mday + "\t" + month + "\t" + wday + "\t" + cmd %>
18
-
19
- <% end %>
@@ -1,17 +0,0 @@
1
- # This section of the file should not be edited
2
- # It was generated by the promotion application and will be overwritten
3
- # when the next promotion occurs.
4
- # The previous section will be preserved
5
- <% @specs.each do |spec|
6
- spec.elements.each("/Specification/Environment") do |env|
7
- env.elements.each("Variable") do |var|
8
- t = var.cdatas.length > 0 ? var.cdatas[0].to_s() : var.text() %>
9
- export <%= var.attributes["Name"] %>="<%= t %>"<% end %>
10
- <% env.elements.each("Alias") do |ali|
11
- t = ali.cdatas.length > 0 ? ali.cdatas[0].to_s() : ali.text()
12
- %><% if ali.attributes["Comment"] %><%= "\n# "+ali.attributes["Comment"]
13
- %><% end %>
14
- alias <%= ali.attributes["Name"] %>='<%= t %>' <%
15
- end
16
- end
17
- end %>
@@ -1,20 +0,0 @@
1
- # This section of the file is generated by the promotion application
2
- # DO NOT EDIT THIS SECTION - your changes will be lost
3
- # You may edit the section before the promotion marker
4
- #______________________________
5
- # generated application flags
6
- <% daemonSpecs = @specs.reject {|s| s.elements["/Specification/Daemon"].nil? } %>
7
- <% daemonSpecs.sort!() do |a, b| %>
8
- <% ap = a.elements["/Specification/Daemon"].attributes["Priority"].to_i || 10 %>
9
- <% bp = b.elements["/Specification/Daemon"].attributes["Priority"].to_i || 10 %>
10
- <% ap <=> bp %>
11
- <% end %>
12
- <% pkgScripts = [] %>
13
- <% daemonSpecs.each do |spec| %>
14
- <%= spec.attributes["Name"] %>_flags="<%= spec.elements["/Specification/Daemon"].attributes["Flags"] %>"
15
- <% pkgScripts << spec.attributes["Name"] %>
16
- <% end %>
17
-
18
- # rc.d(8) packages scripts
19
- # started in the specified order and stopped in reverse order
20
- pkg_scripts="<%= pkgScripts.join(" ") %>"
@@ -1,22 +0,0 @@
1
- # This section of the file should not be edited, even with visudo
2
- # It was generated by the promotion application and will be overwritten
3
- # when the next promotion occurs.
4
- # The previous section will be preserved
5
-
6
- Defaults timestamp_timeout=55
7
-
8
- root ALL = (ALL) ALL
9
- # people in group wheel may run all commands
10
- %wheel ALL = (ALL) ALL
11
-
12
- # Generated user privilege specifications
13
- <% @specs.each do |spec| %>
14
- <% spec.elements.each("/Specification/Sudoers/UserPrivilege") do |priv| %>
15
- <%= sprintf('%-16s', priv.attributes["User"]) %>
16
- <%= " ALL = " %>
17
- <% if priv.attributes["Runas"] %>(<%= priv.attributes["Runas"] %>) <% end %>
18
- <%= (priv.attributes["Password"] || "").downcase() == "true" ? " " : "NOPASSWD: " %>
19
- <%= priv.text().strip() %>
20
-
21
- <% end %>
22
- <% end %>