aboutsummaryrefslogtreecommitdiff
path: root/lib/leap_cli/leapfile.rb
blob: 8895f4dc1fd8b11a45e3100e49bc306ba6837017 (plain)
1
2
3
4
5
6
7
8
9
10
11
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
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
137
138
139
140
141
142
143
144
145
146
147
#
# The Leapfile is the bootstrap configuration file for a LEAP provider.
#
# It is akin to a Gemfile, Rakefile, or Capfile (e.g. it is a ruby file that gets eval'ed)
#

module LeapCli
  def self.leapfile
    @leapfile ||= Leapfile.new
  end

  class Leapfile
    attr_accessor :platform_directory_path
    attr_accessor :provider_directory_path
    attr_accessor :custom_vagrant_vm_line
    attr_accessor :leap_version
    attr_accessor :log
    attr_accessor :vagrant_network
    attr_accessor :environment

    def initialize
      @vagrant_network = '10.5.5.0/24'
    end

    #
    # The way the Leapfile handles pinning of environment (self.environment) is a little tricky.
    # If self.environment is nil, then there is no pin. If self.environment is 'default', then
    # there is a pin to the default environment. The problem is that an environment of nil
    # is used to indicate the default environment in node properties.
    #
    # This method returns the environment tag as needed when filtering nodes.
    #
    def environment_filter
      if self.environment == 'default'
        nil
      else
        self.environment
      end
    end

    def load(search_directory=nil)
      directory = File.expand_path(find_in_directory_tree('Leapfile', search_directory))
      if directory == '/'
        return nil
      else
        #
        # set up paths
        #
        @provider_directory_path = directory
        read_settings(directory + '/Leapfile')
        read_settings(leaprc_path)
        @platform_directory_path = File.expand_path(@platform_directory_path || '../leap_platform', @provider_directory_path)

        #
        # load the platform
        #
        require "#{@platform_directory_path}/platform.rb"
        if !Leap::Platform.compatible_with_cli?(LeapCli::VERSION)
          Util.bail! "This leap command (v#{LeapCli::VERSION}) " +
                     "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " +
                     "You need leap command #{Leap::Platform.compatible_cli.first} to #{Leap::Platform.compatible_cli.last}."
        end
        if !Leap::Platform.version_in_range?(LeapCli::COMPATIBLE_PLATFORM_VERSION)
          Util.bail! "This leap command (v#{LeapCli::VERSION}) " +
                     "is not compatible with the platform #{@platform_directory_path} (v#{Leap::Platform.version}). " +
                     "You need platform version #{LeapCli::COMPATIBLE_PLATFORM_VERSION.first} to #{LeapCli::COMPATIBLE_PLATFORM_VERSION.last}."
        end

        unless @allow_production_deploy.nil?
          Util::log 0, :warning, "in Leapfile: @allow_production_deploy is no longer supported."
        end
        unless @platform_branch.nil?
          Util::log 0, :warning, "in Leapfile: @platform_branch is no longer supported."
        end
        return true
      end
    end

    def set(property, value)
      edit_leaprc(property, value)
    end

    def unset(property)
      edit_leaprc(property)
    end

    private

    #
    # adds or removes a line to .leaprc for this particular provider directory.
    # if value is nil, the line is removed. if not nil, it is added or replaced.
    #
    def edit_leaprc(property, value=nil)
      file_path = leaprc_path
      lines = []
      if File.exists?(file_path)
        regexp = /self\.#{Regexp.escape(property)} = .*? if @provider_directory_path == '#{Regexp.escape(@provider_directory_path)}'/
        File.readlines(file_path).each do |line|
          unless line =~ regexp
            lines << line
          end
        end
      end
      unless value.nil?
        lines << "self.#{property} = #{value.inspect} if @provider_directory_path == '#{@provider_directory_path}'\n"
      end
      File.open(file_path, 'w') do |f|
        f.write(lines.join)
      end
    rescue Errno::EACCES, IOError => exc
      Util::bail! :error, "trying to save ~/.leaprc (#{exc})."
    end

    def leaprc_path
      File.join(ENV['HOME'], '.leaprc')
    end

    def read_settings(file)
      if File.exists? file
        Util::log 2, :read, file
        instance_eval(File.read(file), file)
        validate(file)
      end
    end

    def find_in_directory_tree(filename, directory_tree=nil)
      search_dir = directory_tree || Dir.pwd
      while search_dir != "/"
        Dir.foreach(search_dir) do |f|
          return search_dir if f == filename
        end
        search_dir = File.dirname(search_dir)
      end
      return search_dir
    end

    PRIVATE_IP_RANGES = /(^127\.0\.0\.1)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)/

    def validate(file)
      Util::assert! vagrant_network =~ PRIVATE_IP_RANGES do
        Util::log 0, :error, "in #{file}: vagrant_network is not a local private network"
      end
    end

  end
end