Module: Secryst::Provisioning

Extended by:
Provisioning
Included in:
Provisioning
Defined in:
lib/secryst/provisioning.rb

Overview

Module Secryst::Provisioning is to provision remote models locally and to dispatch them later on.

Defined Under Namespace

Classes: Remotefile, Secrystfile

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#preload_modelsObject

Returns the value of attribute preload_models.



15
16
17
# File 'lib/secryst/provisioning.rb', line 15

def preload_models
  @preload_models
end

#remotesObject

Returns the value of attribute remotes.



15
16
17
# File 'lib/secryst/provisioning.rb', line 15

def remotes
  @remotes
end

Instance Method Details

#add_remote(path) ⇒ Object



17
18
19
20
# File 'lib/secryst/provisioning.rb', line 17

def add_remote(path)
  @remotes << path
  @remotes = @remotes.uniq
end

#download(model, remote:) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/secryst/provisioning.rb', line 129

def download(model, remote:)
  uri = model.uri
  if uri.start_with?("./") || uri.start_with?("../")
    remote_uri = remote.uri
    if remote_uri =~ %r{\A/|\A\w:[\\/]}
      remote_uri = "file://"+remote_uri
    end

    uri = URI(remote_uri).merge(uri).to_s
    uri = uri.sub(%r{\Afile://}, '')
  end

  warn "* Downloading a Secryst model #{model.name}:#{model.version} from #{uri}..."

  data = URI.open(uri).read
  path = @write_path + "/models/" + model.name
  FileUtils.mkdir_p path
  File.write(path + "/version", model.version)
  File.write(path + "/model.zip", data)
  return path + "/model.zip"
end

#locate(name) ⇒ Object

Raises:

  • (StandardError)


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
# File 'lib/secryst/provisioning.rb', line 98

def locate(name)
  # Shortcut this if user gave a filename.
  return name if name =~ %r{[.\\/]}

  prepare_environment

  @loaded_remotes.each do |i|
    model = i.resolve(name)
    if model
      model_path = @read_paths.map do |j|
        path = j + "/models/" + model.name
        next path if File.readable?(path)
        nil
      end.compact.first

      if model_path
        version = File.read(model_path + "/version").to_f
        if version >= model.version
          return model_path + "/model.zip"
        else
          return download(model, remote: i)
        end
      else
        return download(model, remote: i)
      end
    end
  end

  raise StandardError, "Model #{name} not found"
end

#prepare_environmentObject

Raises:

  • (StandardError)


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
# File 'lib/secryst/provisioning.rb', line 22

def prepare_environment
  return if @set_up

  # We provision the environment in the following way:
  # First, we try the SECRYST_DATA environment variable. If that's available,
  # we use it to store the Secryst data we need. Otherwise, we try the following
  # paths:

  possible_paths = [
    "/var/lib/secryst",
    "/usr/local/share/secryst",
    "/usr/share/secryst",
    File.join(Dir.home, ".local/share/secryst")
  ]

  # We find the first writable path to become the primary one. The remaining
  # ones will be used read-only if they exist

  @write_path = nil
  @read_paths = []

  ([ENV["SECRYST_DATA"]] + possible_paths).compact.each do |path|
    FileUtils.mkdir_p(path)
    @write_path = path unless @write_path
  rescue
  ensure
    @read_paths << path if File.readable?(path)
  end

  raise StandardError, "Can't find a writable path for Secryst. Consider setting a SECRYST_DATA environment variable" unless @write_path

  # Now, let's locate the first Secrystfile to be found
  path = Dir.pwd
  secrystfilepath = loop do
    break unless path =~ %r{[/\\]}
    if File.readable?(path + "/Secrystfile")
      break path + "/Secrystfile"
    end
    path = path.sub(%r{[/\\][^/\\]*?\z}, '')
  end

  # It's found, so let's parse it.
  if secrystfilepath
    secrystfile = Secrystfile.new(secrystfilepath)

    @remotes = secrystfile.remotes + @remotes
    @remotes = @remotes.uniq

    @preload_models = secrystfile.models
  end

  # Load the remotes if they are older than 1 minute
  FileUtils.mkdir_p(@write_path + "/remotes/")
  @loaded_remotes = @remotes.map do |uri|
    cache_path = "#{@write_path}/remotes/#{Digest::SHA256.hexdigest(uri)}.yaml"
    if !File.exist?(cache_path)
      data = URI.open(uri).read
      File.write(cache_path, data)
    elsif File.mtime(cache_path) + 60 < Time.now
      begin
        # Just *try* to download it.
        data = URI.open(uri).read
        File.write(cache_path, data)
      rescue
      end
    end
    Remotefile.new(cache_path, uri: uri)
  end

  # Ok we are done now. We still need to resolve the required paths, but for
  # that let's reuse our existing facilities.
  @set_up = true

  @preload_models.each { |i| locate(i) }
end