Class: PushyClient

Inherits:
Object
  • Object
show all
Defined in:
lib/pushy_client/version.rb,
lib/pushy_client.rb,
lib/pushy_client/cli.rb,
lib/pushy_client/whitelist.rb,
lib/pushy_client/job_runner.rb,
lib/pushy_client/heartbeater.rb,
lib/pushy_client/windows_service.rb,
lib/pushy_client/protocol_handler.rb,
lib/pushy_client/periodic_reconfigurer.rb

Overview

This file is provided to you under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

Defined Under Namespace

Classes: CLI, FileDirCleaner, Heartbeater, JobRunner, PeriodicReconfigurer, ProtocolHandler, Whitelist, WindowsService, ZmqContext

Constant Summary collapse

VERSION =
"2.100.0"
PROTOCOL_VERSION =
"2.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ PushyClient

Returns a new instance of PushyClient.



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

def initialize(options)
  @chef_server_url = options[:chef_server_url]
  @client_name     = options[:client_name] || options[:node_name]
  @client_key      = options[:client_key]
  @node_name       = options[:node_name]
  @whitelist       = PushyClient::Whitelist.new(options[:whitelist])
  @hostname        = options[:hostname]
  @file_dir        = options[:file_dir] || '/tmp/pushy'
  @file_dir_expiry = options[:file_dir_expiry] || 86400
  @allowed_overwritable_env_vars = options[:allowed_overwritable_env_vars]

  @allow_unencrypted = options[:allow_unencrypted] || false
  @client_curve_pub_key, @client_curve_sec_key = ZMQ::Util.curve_keypair

  Chef::Log.info("[#{@node_name}] using config file path: '#{Chef::Config[:config_file]}'")

  if @chef_server_url =~ /\/organizations\/+([^\/]+)\/*/
    @org_name = $1
  else
    raise "chef_server must end in /organizations/ORG_NAME"
  end

  @incarnation_id = UUIDTools::UUID.random_create

  # State is global and persists across stops and starts
  @job_runner = JobRunner.new(self)
  @heartbeater = Heartbeater.new(self)
  @protocol_handler = ProtocolHandler.new(self)
  @periodic_reconfigurer = PeriodicReconfigurer.new(self)
  @file_dir_cleaner = FileDirCleaner.new(self)

  @reconfigure_lock = Mutex.new

  Chef::Log.info "[#{node_name}] Using node name: #{node_name}"
  Chef::Log.info "[#{node_name}] Using org name: #{org_name}"
  Chef::Log.info "[#{node_name}] Using Chef server: #{chef_server_url}"
  Chef::Log.info "[#{node_name}] Using private key: #{client_key}"
  Chef::Log.info "[#{node_name}] Incarnation ID: #{incarnation_id}"
  Chef::Log.info "[#{node_name}] Allowing fallback to unencrypted connection: #{allow_unencrypted}"
end

Instance Attribute Details

#allow_unencryptedObject (readonly)

Returns the value of attribute allow_unencrypted.



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

def allow_unencrypted
  @allow_unencrypted
end

#allowed_overwritable_env_varsObject (readonly)

Returns the value of attribute allowed_overwritable_env_vars.



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

def allowed_overwritable_env_vars
  @allowed_overwritable_env_vars
end

#chef_server_urlObject

Returns the value of attribute chef_server_url.



75
76
77
# File 'lib/pushy_client.rb', line 75

def chef_server_url
  @chef_server_url
end

#client_curve_pub_keyObject (readonly)

crypto



87
88
89
# File 'lib/pushy_client.rb', line 87

def client_curve_pub_key
  @client_curve_pub_key
end

#client_curve_sec_keyObject (readonly)

Returns the value of attribute client_curve_sec_key.



88
89
90
# File 'lib/pushy_client.rb', line 88

def client_curve_sec_key
  @client_curve_sec_key
end

#client_keyObject

Returns the value of attribute client_key.



77
78
79
# File 'lib/pushy_client.rb', line 77

def client_key
  @client_key
end

#client_nameObject

Returns the value of attribute client_name.



76
77
78
# File 'lib/pushy_client.rb', line 76

def client_name
  @client_name
end

#configObject (readonly)

Returns the value of attribute config.



96
97
98
# File 'lib/pushy_client.rb', line 96

def config
  @config
end

#file_dirObject (readonly)

Returns the value of attribute file_dir.



93
94
95
# File 'lib/pushy_client.rb', line 93

def file_dir
  @file_dir
end

#file_dir_expiryObject (readonly)

Returns the value of attribute file_dir_expiry.



94
95
96
# File 'lib/pushy_client.rb', line 94

def file_dir_expiry
  @file_dir_expiry
end

#hostnameObject

Returns the value of attribute hostname.



80
81
82
# File 'lib/pushy_client.rb', line 80

def hostname
  @hostname
end

#incarnation_idObject (readonly)

Returns the value of attribute incarnation_id.



82
83
84
# File 'lib/pushy_client.rb', line 82

def incarnation_id
  @incarnation_id
end

#legacy_modeObject (readonly)

indicate we’ve fallen back to 1.x



83
84
85
# File 'lib/pushy_client.rb', line 83

def legacy_mode
  @legacy_mode
end

#node_nameObject

Returns the value of attribute node_name.



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

def node_name
  @node_name
end

#org_nameObject

Returns the value of attribute org_name.



78
79
80
# File 'lib/pushy_client.rb', line 78

def org_name
  @org_name
end

#using_curveObject (readonly)

Returns the value of attribute using_curve.



90
91
92
# File 'lib/pushy_client.rb', line 90

def using_curve
  @using_curve
end

#whitelistObject

Returns the value of attribute whitelist.



81
82
83
# File 'lib/pushy_client.rb', line 81

def whitelist
  @whitelist
end

Instance Method Details

#abortObject



193
194
195
# File 'lib/pushy_client.rb', line 193

def abort
  @job_runner.abort
end

#commit(job_id, command, opts) ⇒ Object



185
186
187
# File 'lib/pushy_client.rb', line 185

def commit(job_id, command, opts)
  @job_runner.commit(job_id, command, opts)
end

#heartbeat_received(incarnation_id, sequence) ⇒ Object



197
198
199
# File 'lib/pushy_client.rb', line 197

def heartbeat_received(incarnation_id, sequence)
  @heartbeater.heartbeat_received(incarnation_id, sequence)
end

#job_stateObject



169
170
171
# File 'lib/pushy_client.rb', line 169

def job_state
  @job_runner.job_state
end

#log_exception(message, exception) ⇒ Object



201
202
203
# File 'lib/pushy_client.rb', line 201

def log_exception(message, exception)
  Chef::Log.error("[#{node_name}] #{message}: #{exception}\n#{exception.backtrace.join("\n")}")
end

#on_job_state_change(&block) ⇒ Object



213
214
215
# File 'lib/pushy_client.rb', line 213

def on_job_state_change(&block)
  @job_runner.on_job_state_change(&block)
end

#on_server_availability_change(&block) ⇒ Object



205
206
207
# File 'lib/pushy_client.rb', line 205

def on_server_availability_change(&block)
  @heartbeater.on_server_availability_change(&block)
end

#online?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/pushy_client.rb', line 209

def online?
  @heartbeater.online?
end

#reconfigureObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/pushy_client.rb', line 124

def reconfigure
  first = true
  while !@job_runner.safe_to_reconfigure? do
    Chef::Log.info "[#{node_name}] Job in flight, delaying reconfigure" if first
    first = false
    sleep 5
  end

  @reconfigure_lock.synchronize do
    Chef::Log.info "[#{node_name}] Reconfiguring client / reloading keys ..."

    @config = get_config

    @job_runner.reconfigure
    @protocol_handler.reconfigure
    @heartbeater.reconfigure
    @periodic_reconfigurer.reconfigure

    Chef::Log.info "[#{node_name}] Reconfigured client."
  end
  trigger_gc
end

#run(job_id) ⇒ Object



189
190
191
# File 'lib/pushy_client.rb', line 189

def run(job_id)
  @job_runner.run(job_id)
end

#send_command(command, job_id, params = {}) ⇒ Object



173
174
175
# File 'lib/pushy_client.rb', line 173

def send_command(command, job_id, params = {})
  @protocol_handler.send_command(command, job_id, params)
end

#send_heartbeat(sequence) ⇒ Object



177
178
179
# File 'lib/pushy_client.rb', line 177

def send_heartbeat(sequence)
  @protocol_handler.send_heartbeat(sequence)
end

#startObject



98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/pushy_client.rb', line 98

def start
  Chef::Log.info "[#{node_name}] Starting client ..."

  @config = get_config

  @job_runner.start
  @protocol_handler.start
  @heartbeater.start
  @periodic_reconfigurer.start
  @file_dir_cleaner.start

  Chef::Log.info "[#{node_name}] Started client."
end

#stopObject



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/pushy_client.rb', line 112

def stop
  Chef::Log.info "[#{node_name}] Stopping client ..."

  @job_runner.stop
  @protocol_handler.stop
  @heartbeater.stop
  @periodic_reconfigurer.stop
  @file_dir_cleaner.stop

  Chef::Log.info "[#{node_name}] Stopped client."
end

#trigger_gcObject



159
160
161
162
163
164
165
166
167
# File 'lib/pushy_client.rb', line 159

def trigger_gc
  # We have a tendency to bloat up because GCs aren't forced; this tries to keep things a little bit saner.
  before_stat = GC.stat()
  GC.start()
  after_stat = GC.stat()
  stat = :count
  delta = after_stat[stat] - before_stat[stat]
  Chef::Log.info("[#{node_name}] Forced GC; Stat #{stat} changed #{delta}")
end

#trigger_reconfigureObject



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/pushy_client.rb', line 147

def trigger_reconfigure
  # Many of the threads triggering a reconfigure will get destroyed DURING
  # a reconfigure, so we need to spawn a separate thread to take care of it.
  Thread.new do
    begin
      reconfigure
    rescue
      log_exception("Error reconfiguring", $!)
    end
  end
end

#update_reconfigure_deadline(delay) ⇒ Object



181
182
183
# File 'lib/pushy_client.rb', line 181

def update_reconfigure_deadline(delay)
  @periodic_reconfigurer.update_reconfigure_deadline(delay)
end