Module: Pawnee::Actions

Included in:
Base
Defined in:
lib/pawnee/pawnee/actions.rb,
lib/pawnee/pawnee/actions/user.rb,
lib/pawnee/pawnee/actions/compile.rb,
lib/pawnee/pawnee/actions/package.rb,
lib/pawnee/pawnee/actions/base_model.rb,
lib/pawnee/pawnee/actions/inject_into_file.rb

Overview

The pawnee gem provides the Pawnee::Base class which includes Thor::Actions, ThorSsh::Actions. Pawnee::Base also adds in its own actions from the pawnee gem

Defined Under Namespace

Classes: BaseModel, Compile, User

Instance Method Summary collapse

Instance Method Details

#add_user_to_group(login, group) ⇒ Object

Adds the user (specified by login) to the group



6
7
8
9
10
11
# File 'lib/pawnee/pawnee/actions/user.rb', line 6

def add_user_to_group(, group)
  user = self.user()
  user.groups << group
  user.groups = user.groups.sort.uniq
  user.save
end

#compile(url, temp_dir, options = {}) ⇒ Object

Takes a tar.gz or zip file and unzips it, and runs the standard ./configure, make, sudo make install

It attempts to raise an exception at any compilation failure.

compile 'http://nginx.org/download/nginx-1.2.0.tar.gz'

Parameters

url<String>

The url to download

temp_dir<String>

Where the compilation should take place

options<Hash>

Hash of options, see below

Options

#compile requires that you either specify a :bin_file option that the method can check for on the remote system, or that you pass a block that returns true if the app has already been installed

:bin_file - the name of an executable that the method can check for in the path :config_options - a string of options to pass to the ./configure command. :skip_configure - skips the configure step

Block

You can also pass a block that if it returns true, it will not recompile. So the general idea is return true if the exe is already installed.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/pawnee/pawnee/actions/compile.rb', line 31

def compile(url, temp_dir, options={})
  # TODO: Add invoke/revoke support using action(...), maybe 
  # make things run via Thor::Group
  
  installed = false
  if options[:bin_file]
    # Check if the bin file is installed
    installed = exec("which #{options[:bin_file]}", :log_stderr => false).strip != ''
  else
    raise "You must pass :bin_file or a block to compile" unless block_given?
    installed = yield()
  end
  
  if installed
    say_status :already_compiled, url, :blue
    return true
  else
    
    track_modification!
    # Compile and install
    Compile.new(self, url, temp_dir, options)
  end
end

#create_user(attributes) ⇒ Object



18
19
20
# File 'lib/pawnee/pawnee/actions/user.rb', line 18

def create_user(attributes)
  User.new(self, attributes).save
end

#delete_user(login) ⇒ Object



22
23
24
# File 'lib/pawnee/pawnee/actions/user.rb', line 22

def delete_user()
  User.new(self, {:login => }).destroy
end

#insert_into_file(destination, *args, &block) ⇒ Object Also known as: inject_into_file

Adds a :once option that will only do the action the first time it is run (it will check for the text before it injects it each time)



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/pawnee/pawnee/actions/inject_into_file.rb', line 6

def insert_into_file(destination, *args, &block)
  if block_given?
    data, config = block, args.shift
  else
    data, config = args.shift, args.shift
  end
  
  # Get the data if its a proc
  data = data.call if data.is_a?(Proc)
  
  if destination_files.binread(destination)[data]
    say_status :identical, destination
    # Don't run again, the text is already in place
    return
  end
  
  action Thor::Actions::InjectIntoFile.new(self, destination, data, config)
end

#install_package(package_name, version = nil) ⇒ Object

Installs a package using the operating system’s package management system (currentl apt-get only)

install_package 'mysql-server5'
install_package 'gcc', '4.5'

Parameters

package_name<String>

The name of package to be installed

version<String>

The version of the package



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/pawnee/pawnee/actions/package.rb', line 57

def install_package(package_name, version=nil)
  update_package_list
  
  if package_installed?(package_name)
    say_status "package already installed", package_name
  else
    package_name = "#{package_name}=#{version}" if version
    track_modification!
    as_root do
      exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y install #{package_name}", :no_pty => true)
    end
    say_status "installed package", package_name.gsub('=', ' ')
  end
end

#install_packages(*package_names) ⇒ Object

Installs a set of packages, use install_package if you wish to specify a version

install_packages 'build-essential', 'zlib1g-dev'

Parameters

packages<Array>

An array of strings of package names



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/pawnee/pawnee/actions/package.rb', line 93

def install_packages(*package_names)
  packages = nil
  # # TODO: pull in versions and use this to get a better 
  # 
  # as_root do
  #   packages = exec("dpkg --get-selections", :no_pty => true)
  # end
  # 
  # installed_package_names = []
  # packages.split(/\n/).each do |package|
  #   name, version = package.split(/\s+/)
  #   installed_package_names << name
  # end


  as_root do
    update_package_list
    packages = exec("dpkg -l", :no_pty => true)
  end
  
  installed_package_names = []
  packages.split(/\n/).grep(/^ii /).each do |package|
    _, name, version = package.split(/\s+/)
    installed_package_names << name
  end

  need_to_install_packages = []
  
  package_names.flatten.each do |package_name|
    if installed_package_names.include?(package_name)
      say_status "package already installed", package_name, :blue
    else
      need_to_install_packages << package_name
    end
  end
  
  if need_to_install_packages.size > 0
    track_modification!
    as_root do
      say_status "installing packages", need_to_install_packages.join(', ')
      exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y install #{need_to_install_packages.join(' ')}", :no_pty => true)
    end
  end
end

#installed_package_version(package_name) ⇒ Object

Returns the version of a package that is installed

installed_package_version 'memcached'
-> 1.4.7-0.1ubuntu1

Parameters

package_name<String>

The name of package



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/pawnee/pawnee/actions/package.rb', line 31

def installed_package_version(package_name)
  packages = nil
  as_root do
    packages = exec("dpkg -l", :no_pty => true)
  end
  
  packages.split(/\n/).grep(/^ii /).each do |package|
    _, name, version = package.split(/\s+/)
    
    if name == package_name
      return version
    end
  end
  
  return nil
end

#package_installed?(package_name, version = nil) ⇒ Boolean

Returns true if the package is installed. If a version is listed, it will make sure it matches the version.

package_installed? 'memcached'
-> true

package_installed? 'memcached', '1.4.7-0.1ubuntu1'
-> false

Parameters

package_name<String>

The name of package

Returns:

  • (Boolean)


15
16
17
18
19
20
21
22
# File 'lib/pawnee/pawnee/actions/package.rb', line 15

def package_installed?(package_name, version=nil)
  installed_version = installed_package_version(package_name)
  if version
    return (installed_version == version)
  else
    return !!installed_version
  end
end

#pawnee_setup_actions(args = [], options = {}, config = {}) ⇒ Object

This is copied in from thor/actions.rb#initialize, we can’t extend from a module, so we just move this setup to a method



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/pawnee/pawnee/actions.rb', line 14

def pawnee_setup_actions(args=[], options={}, config={}) #:nodoc:
  self.behavior = case config[:behavior].to_s
    when "force", "skip"
      _cleanup_options_and_set(options, config[:behavior])
      :invoke
    when "revoke"
      :revoke
    else
      :invoke
  end
  
  yield
  self.destination_root = config[:destination_root]
end

#remove_package(package_name) ⇒ Object

Removes package_name

Parameters

package_name<String>

The name of package



142
143
144
145
146
147
148
149
150
151
# File 'lib/pawnee/pawnee/actions/package.rb', line 142

def remove_package(package_name)
  if package_installed?(package_name)
    say_status "removed package", package_name
    as_root do
      exec("DEBIAN_FRONTEND=noninteractive apt-get -q -y remove #{package_name}", :no_pty => true)
    end
  else
    say_status "package not removed", package_name
  end
end

#remove_packages(*package_names) ⇒ Object

Removes a set of packages, use remove_package if you wish to specify a version

remove_packages 'build-essential', 'zlib1g-dev'

Parameters

packages<Array>

An array of strings of package names



160
161
162
163
164
# File 'lib/pawnee/pawnee/actions/package.rb', line 160

def remove_packages(*package_names)
  package_names.flatten.each do |package_name|
    remove_package(package_name)
  end
end

#update_package_listObject

Updates the package manager to the most recent list of packages. Also only runs this once per group of operations to prevent this from happening too much.



75
76
77
78
79
80
81
82
83
84
# File 'lib/pawnee/pawnee/actions/package.rb', line 75

def update_package_list
  # TODO: this needs to be per server
  unless defined?(@@packages_updated) && @@packages_updated[server]
    @@packages_updated ||= {}
    @@packages_updated[server] = true
    as_root do
      exec('DEBIAN_FRONTEND=noninteractive apt-get -q -y update', :no_pty => true)
    end
  end
end

#user(login) ⇒ Object

Return the user object for the login



14
15
16
# File 'lib/pawnee/pawnee/actions/user.rb', line 14

def user()
  return User.new(self, {:login => })
end