Class: Gluez::Context

Inherits:
Object show all
Defined in:
lib/gluez/context.rb

Overview

A context in gluez is a unit of work. It contains one or multiple resources. Context-wide variables can set/get as properties. A context can include a recipe, which is an isolated context of it’s own. We can set properties of a recipe from the outer context. This enables us to write modular and reusable recipes.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil, name = nil, user = nil, type = nil, &block) ⇒ Context

Returns a new instance of Context.



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/gluez/context.rb', line 13

def initialize(parent=nil, name=nil, user=nil, type=nil, &block)
  @parent = parent
  @name = name
  @user = user
  @type = type
  
  @resources = []
  @properties = {}
  
  @included_user_contexts = []
  
  $gluez = self
  
  self.include_user! "root" if self == self.root
  
  instance_eval(&block) if block
  
  if self.root == self
    self.generate($simulate == true)
  else
    $gluez = parent
  end
end

Instance Attribute Details

#included_user_contextsObject (readonly)

A reference to the outer context



11
12
13
# File 'lib/gluez/context.rb', line 11

def included_user_contexts
  @included_user_contexts
end

#parentObject (readonly)

A reference to the outer context



11
12
13
# File 'lib/gluez/context.rb', line 11

def parent
  @parent
end

#resourcesObject (readonly)

An array of all resources in this context



8
9
10
# File 'lib/gluez/context.rb', line 8

def resources
  @resources
end

Class Method Details

.load_resourcesObject



196
197
198
199
200
201
202
203
204
205
# File 'lib/gluez/context.rb', line 196

def self.load_resources
  dirs = [File.dirname($0), File.dirname(__FILE__)].collect{|d| "#{d}/resources"}

  dirs.each do |dir|
    next unless File.exist?(dir)
    Dir.glob(dir + "/*") do |file|
      require file
    end
  end
end

.register(method_name, &block) ⇒ Object



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/gluez/context.rb', line 207

def self.register(method_name, &block)
  define_method method_name do |name, &block2|
    res = Gluez::Resource.new(self, method_name, name)

    res.class.class_eval do
      define_method("ready!".to_sym) do
        res.instance_eval(&block2) if block2
        res.validate!
      end
    end
    
    res.instance_eval(&block)

    self.root.resources << res
  end
end

Instance Method Details

#default(name, name2) ⇒ Object



54
55
56
57
58
59
60
61
62
# File 'lib/gluez/context.rb', line 54

def default(name, name2)
  unless @properties.key?(name)
    if name2.is_a?(Symbol)
      set(name, get(name2))
    else
      set(name, name2)
    end
  end
end

#expect(name) ⇒ Object



64
65
66
# File 'lib/gluez/context.rb', line 64

def expect(name)
  raise "missing #{name}" unless get(name)
end

#generate(simulate) ⇒ Object

Loops through all resources, collect their generated code, format and return it.



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/gluez/context.rb', line 131

def generate(simulate)
  code = "#!/bin/bash"

  root_user_context = @included_user_contexts.detect{|ctx| ctx.user == "root"}
  raise "no root user context could be found" unless root_user_context
  
  user_contexts = @included_user_contexts - [root_user_context]

  existing_resources = Array.new(@resources)

  root_user_context.instance_eval do |ctx|
    user_contexts.each do |user_ctx|
      create_group(user_ctx.user) do
        gid user_ctx.get(:uid)
      end
    
      create_user(user_ctx.user) do
        uid user_ctx.get(:uid)
        gid user_ctx.get(:uid)
      end
      
      ['.gluez', '.gluez/path', 'tmp', 'backup', 'bin', '.ssh', 'log'].each do |dir_name|
        dir(dir_name) do
          as_user user_ctx.user
        end
      end
      
      if user_ctx.get(:authorized_keys)
        transfer "~/.ssh/authorized_keys" do
          as_user user_ctx.user
          chmod 400
          content user_ctx.get(:authorized_keys).join("\n")
        end
      end
        
      transfer "~/.profile" do
        as_user  user_ctx.user
        chmod   644
        content File.read("#{File.dirname(__FILE__)}/templates/profile.erb")
      end
      
      if user_ctx.get(:sudo)
        transfer "/etc/sudoers.d/#{user_ctx.user}" do
          chmod 440
          content "#{user_ctx.user} ALL=(ALL) NOPASSWD: ALL"
        end
      end
      
    end
  end
  
  # sort resources to always create users/groups first
  @resources = (@resources - existing_resources) + existing_resources
  
  code += "\n" + @resources.collect do |res|
    res.generate(simulate).join("\n")
  end.join("\n")

  code += "\n" + @resources.select{|r| !r.lazy}.collect do |res|
    res.function_name
  end.join("\n")
  
  puts Gluez::format(code)
end

#get(name) ⇒ Object

Get a property value



89
90
91
# File 'lib/gluez/context.rb', line 89

def get(name)
  @properties[name]
end

#home_dirObject



50
51
52
# File 'lib/gluez/context.rb', line 50

def home_dir
  self.user == "root" ? "/root" : "/home/#{self.user}"
end

#include_library_recipe(library_dir, name, &block) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/gluez/context.rb', line 93

def include_library_recipe(library_dir, name, &block)
  raise "include_recipe is only allowed in user context" if self == self.root
  Gluez::Context.new(self, name, nil, :recipe) do |c|
    c.instance_eval(&block) if block
    load "#{library_dir}/recipes/#{name}/#{name}.rb"
  end
end

#include_recipe(name, &block) ⇒ Object

Includes a recipe. A new context will be created. The passed block will be executed in the scope of the new context.



102
103
104
# File 'lib/gluez/context.rb', line 102

def include_recipe(name, &block)
  self.include_library_recipe(File.dirname($0), name, &block)
end

#include_user(name, failsafe = false, &block) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/gluez/context.rb', line 110

def include_user(name, failsafe=false, &block)
  raise "include_user is only allowed in root context" unless self == self.root
  Gluez::Context.new(self, name, name, :user) do |c|
    if block
      c.instance_eval(&block) 
    end
    
    c.root.included_user_contexts << c
    
    f = "#{File.dirname($0)}/users/#{name}.rb"
    
    if File.exist?(f)
      load(f)
    else
      raise "could not find user context file #{f}" unless failsafe
    end
    
  end
end

#include_user!(name, &block) ⇒ Object



106
107
108
# File 'lib/gluez/context.rb', line 106

def include_user!(name, &block)
  self.include_user(name, true, &block)
end

#locate(resource) ⇒ Object



68
69
70
71
72
73
74
75
76
77
# File 'lib/gluez/context.rb', line 68

def locate(resource)
  case @type
    when :recipe
      File.dirname($0) + "/recipes/#{@name}/files/#{resource}"
    when :user
      File.dirname($0) + "/users/files/#{resource}"
    else
      File.dirname($0) + "/files/#{resource}"
  end
end

#read(resource) ⇒ Object



79
80
81
# File 'lib/gluez/context.rb', line 79

def read(resource)
  File.read $gluez.locate(resource)
end

#rootObject

Returns the outer most context



38
39
40
# File 'lib/gluez/context.rb', line 38

def root
  self.parent ? self.parent.root : self
end

#set(name, value) ⇒ Object

Set a property value



84
85
86
# File 'lib/gluez/context.rb', line 84

def set(name, value)
  @properties[name] = value
end

#userObject



42
43
44
45
46
47
48
# File 'lib/gluez/context.rb', line 42

def user
  if @user
    @user
  else
    @parent ? @parent.user : nil
  end
end