Module: VeeweeToPacker

Defined in:
lib/veewee-to-packer.rb,
lib/veewee-to-packer/error.rb,
lib/veewee-to-packer/version.rb,
lib/veewee-to-packer/builders/vmware.rb,
lib/veewee-to-packer/builders/virtualbox.rb

Defined Under Namespace

Modules: Builders Classes: Error

Constant Summary collapse

BUILDERS =
{
  "virtualbox" => Builders::VirtualBox,
  "vmware" => Builders::VMware
}
VERSION =
"0.3.0"

Class Method Summary collapse

Class Method Details

.convert(input, output, builders) ⇒ Object

Converts the given Veewee template into a Packer template, outputting the JSON to the given output path. The builders that the template will contain is specified by ‘builders`.



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/veewee-to-packer.rb', line 20

def self.convert(input, output, builders)
  builders = builders.map do |builder|
    klass = BUILDERS[builder.downcase]
    raise Error, "No such builder: #{builder}" if !klass
    klass
  end

  # Make the output directory
  output = Pathname.new(output)
  output.mkpath

  # Determine the directory where the template is
  input_dir = Pathname.new(input).parent

  # Load the definition file and capture its configuration
  begin
    load File.expand_path(input)
  rescue LoadError => e
    raise Error, "Error loading input template: #{e}"
  end

  definition = Veewee::Definition.captured

  # This will keep track of any warnings (errors are raised) that
  # we have during the conversion process.
  warnings = []

  # This will be the packer template contents that we'll turn to JSON
  template = {}

  # First, convert the postinstall_files into a shell provisioning step
  if definition[:postinstall_files]
    provisioner = { "type" => "shell" }
    provisioner["scripts"] = definition.delete(:postinstall_files).map do |script|
      scripts_dir = output.join("scripts")
      scripts_dir.mkpath

      script_file_src = Pathname.new(File.expand_path(script, input_dir))
      script_file_dest = scripts_dir.join(script_file_src.basename)

      if !script_file_src.file?
        raise Error, "File could not be found: #{script_file_src}\n" +
          "Please make sure the Veewee definition you're converting\n" +
          "was not copied without its accompanying shell scripts.\n" +
          "This error is usually caused by copying the definition without\n" +
          "copying all the required files. Otherwise, this definition is\n" +
          "broken in Veewee too."
      end

      FileUtils.cp(script_file_src, script_file_dest)

      "scripts/#{script_file_dest.basename}"
    end

    if definition[:sudo_cmd]
      override = {}
      provisioner["override"] = override

      builders.each do |builder|
        execute_command = definition[:sudo_cmd].
          gsub("%p", definition[:ssh_password]).
          gsub("%f", "{{.Path}}")

        override[builder.name] = {
          "execute_command" => execute_command
        }
      end
    end

    template["provisioners"] = [provisioner]

    # Unused fields
    if definition[:postinstall_timeout]
      definition.delete(:postinstall_timeout)
      warnings << "':postinstall_timeout' doesn't exist in Packer."
    end
  end

  # Sometimes there are empty kickstart files... we just ignore that.
  if definition[:kickstart_file] == ""
    definition.delete(:kickstart_file)
  end

  # Some overall things
  if definition[:hooks]
    definition.delete(:hooks)
    warnings << ":hooks are not supported by Packer."
  end

  if definition[:params]
    definition.delete(:params)
    warnings << ":params are not supported by Packer."
  end

  if definition[:kvm]
    definition.delete(:kvm)
    warnings << ":kvm not supported by Packer."
  end

  # Build the builders
  template["builders"] = builders.map do |builder|
    config, build_warnings = builder.convert(definition.dup, input_dir, output)
    if build_warnings && !build_warnings.empty?
      build_warnings.each do |warning|
        warnings << "Builder '#{builder.name}': #{warning}"
      end
    end

    config
  end

  output.join("template.json").open("w") do |f|
    f.write(JSON.pretty_generate(template))
  end

  warnings
end