Class: Pocketknife

Inherits:
Object
  • Object
show all
Defined in:
lib/pocketknife.rb,
lib/pocketknife/node.rb,
lib/pocketknife/errors.rb,
lib/pocketknife/version.rb,
lib/pocketknife/node_manager.rb

Overview

Pocketknife

About

Pocketknife is a devops tool for managing computers running chef-solo. Using Pocketknife, you create a project that describes the configuration of your computers and then apply it to bring them to the intended state.

For information on using the pocketknife tool, please see the README.md file. The rest of this documentation is intended for those writing code using the Pocketknife API.

Important methods

  • Pocketknife.cli runs the command-line interpreter, whichi in turn executes the methods below.

  • #initialize creates a new Pocketknife instance.

  • #create creates a new project.

  • #deploy deploys configurations to nodes, which uploads and applies.

  • #upload uploads configurations to nodes.

  • #apply applies existing configurations to nodes.

  • #node finds a node to upload or apply configurations.

Important classes

  • Node describes how to upload and apply configurations to nodes, which are remote computers.

  • NodeManager finds, checks and manages nodes.

  • NodeError describes errors encountered when using nodes.

Defined Under Namespace

Modules: Version Classes: ExecutionError, NoSuchNode, Node, NodeError, NodeManager, NotInstalling, UnsupportedInstallationPlatform

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Pocketknife

Instantiate a new Pocketknife.

Parameters:

  • [Boolean] (Hash)

    a customizable set of options



156
157
158
159
160
161
# File 'lib/pocketknife.rb', line 156

def initialize(opts={})
  self.verbosity   = opts[:verbosity]
  self.can_install = opts[:install]

  self.node_manager = NodeManager.new(self)
end

Instance Attribute Details

#can_installObject

Can chef and its dependencies be installed automatically if not found? true means perform installation without prompting, false means quit if chef isn’t available, and nil means prompt the user for input.



147
148
149
# File 'lib/pocketknife.rb', line 147

def can_install
  @can_install
end

#node_managerObject

NodeManager instance.



150
151
152
# File 'lib/pocketknife.rb', line 150

def node_manager
  @node_manager
end

#verbosityObject

Amount of detail to display? true means verbose, nil means normal, false means quiet.



144
145
146
# File 'lib/pocketknife.rb', line 144

def verbosity
  @verbosity
end

Class Method Details

.cli(args) ⇒ Object

Runs the interpreter using arguments provided by the command-line. Run pocketknife -h or review the code below to see what command-line arguments are accepted.

Example:

# Display command-line help:
Pocketknife.cli('-h')

Parameters:

  • args (Array<String>)

    A list of arguments from the command-line, which may include options (e.g. -h).



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
# File 'lib/pocketknife.rb', line 46

def self.cli(args)
  pocketknife = Pocketknife.new

  OptionParser.new do |parser|
    parser.banner = <<-HERE
USAGE: pocketknife [options] [nodes]

EXAMPLES:
# Create a new project called PROJECT
pocketknife -c PROJECT

# Apply configuration to a node called NODE
pocketknife NODE

OPTIONS:
    HERE

    options = {}

    parser.on("-c", "--create PROJECT", "Create project") do |name|
      pocketknife.create(name)
      return
    end

    parser.on("-V", "--version", "Display version number") do |name|
      puts "Pocketknife #{Pocketknife::Version::STRING}"
      return
    end

    parser.on("-v", "--verbose", "Display detailed status information") do |name|
      pocketknife.verbosity = true
    end

    parser.on("-q", "--quiet", "Display minimal status information") do |v|
      pocketknife.verbosity = false
    end

    parser.on("-u", "--upload", "Upload configuration, but don't apply it") do |v|
      options[:upload] = true
    end

    parser.on("-a", "--apply", "Runs cheef to apply already-uploaded configuration") do |v|
      options[:apply] = true
    end

    parser.on("-i", "--install", "Install Chef automatically") do |v|
      pocketknife.can_install = true
    end

    parser.on("-I", "--noinstall", "Don't install Chef automatically") do |v|
      pocketknife.can_install = false
    end

    begin
      arguments = parser.parse!
    rescue OptionParser::MissingArgument => e
      puts parser
      puts
      puts "ERROR: #{e}"
      exit -1
    end

    nodes = arguments

    if nodes.empty?
      puts parser
      puts
      puts "ERROR: No nodes specified."
      exit -1
    end

    begin
      if options[:upload]
        pocketknife.upload(nodes)
      end

      if options[:apply]
        pocketknife.apply(nodes)
      end

      if not options[:upload] and not options[:apply]
        pocketknife.deploy(nodes)
      end
    rescue NodeError => e
      puts "! #{e.node}: #{e}"
      exit -1
    end
  end
end

.versionString

Returns the software’s version.

Returns:

  • (String)

    A version string.



139
140
141
# File 'lib/pocketknife.rb', line 139

def self.version
  return "0.0.1"
end

Instance Method Details

#apply(nodes) ⇒ Object

Applies configurations to remote nodes.

Parameters:

  • nodes (Array<String>)

    A list of node names.



245
246
247
248
249
250
251
# File 'lib/pocketknife.rb', line 245

def apply(nodes)
  node_manager.assert_known(nodes)

  for node in nodes
    node_manager.find(node).apply
  end
end

#create(project) {|path| ... } ⇒ Object

Creates a new project directory.

Parameters:

  • project (String)

    The name of the project directory to create.

Yields:

  • (path)

    Yields status information to the optionally supplied block.

Yield Parameters:

  • path (String)

    The path of the file or directory created.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/pocketknife.rb', line 188

def create(project)
  self.say("* Creating project in directory: #{project}")

  dir = Pathname.new(project)

  %w[
    nodes
    roles
    cookbooks
    site-cookbooks
  ].each do |subdir|
    target = (dir + subdir)
    unless target.exist?
      FileUtils.mkdir_p(target)
      self.say("- #{target}/")
    end
  end

  return true
end

#deploy(nodes) ⇒ Object

Deploys configuration to the nodes, calls #upload and #apply.

@params nodes A list of node names.



219
220
221
222
223
224
225
226
227
# File 'lib/pocketknife.rb', line 219

def deploy(nodes)
  node_manager.assert_known(nodes)

  Node.prepare_upload do
    for node in nodes
      node_manager.find(node).deploy
    end
  end
end

#node(name) ⇒ Object

Returns a Node instance.

@param name The name of the node.



212
213
214
# File 'lib/pocketknife.rb', line 212

def node(name)
  return node_manager.find(name)
end

#say(message, importance = nil) ⇒ Object

Display a message, but only if it’s important enough

Parameters:

  • message (String)

    The message to display.

  • importance (Boolean) (defaults to: nil)

    How important is this? true means important, nil means normal, false means unimportant.



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/pocketknife.rb', line 167

def say(message, importance=nil)
  display = \
    case self.verbosity
    when true
      true
    when nil
      importance != false
    else
      importance == true
    end

  if display
    puts message
  end
end

#upload(nodes) ⇒ Object

Uploads configuration information to remote nodes.

Parameters:

  • nodes (Array<String>)

    A list of node names.



232
233
234
235
236
237
238
239
240
# File 'lib/pocketknife.rb', line 232

def upload(nodes)
  node_manager.assert_known(nodes)

  Node.prepare_upload do
    for node in nodes
      node_manager.find(node).upload
    end
  end
end