Class: Chef::Provider::Package::Dnf::PythonHelper

Inherits:
Object
  • Object
show all
Extended by:
Mixin::Which
Includes:
Singleton
Defined in:
lib/chef/provider/package/dnf/python_helper.rb

Constant Summary collapse

DNF_HELPER =
::File.expand_path(::File.join(::File.dirname(__FILE__), "dnf_helper.py")).freeze
DNF_COMMAND =
"#{which("python3")} #{DNF_HELPER}"

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Mixin::Which

which

Instance Attribute Details

#stderrObject

Returns the value of attribute stderr.



31
32
33
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 31

def stderr
  @stderr
end

#stdinObject

Returns the value of attribute stdin.



29
30
31
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 29

def stdin
  @stdin
end

#stdoutObject

Returns the value of attribute stdout.



30
31
32
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 30

def stdout
  @stdout
end

#wait_thrObject

Returns the value of attribute wait_thr.



32
33
34
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 32

def wait_thr
  @wait_thr
end

Instance Method Details

#add_version(hash, version) ⇒ Object

i couldn’t figure out how to decompose an evr on the python side, it seems reasonably painless to do it in ruby (generally massaging nevras in the ruby side is HIGHLY discouraged – this is an “every rule has an exception” exception – any additional functionality should probably trigger moving this regexp logic into python)



60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 60

def add_version(hash, version)
  epoch = nil
  if version =~ /(\S+):(\S+)/
    epoch, version = $1, $2
  end
  if version =~ /(\S+)-(\S+)/
    version, release = $1, $2
  end
  hash["epoch"] = epoch unless epoch.nil?
  hash["release"] = release unless release.nil?
  hash["version"] = version
end

#build_query(action, provides, version, arch) ⇒ Object



73
74
75
76
77
78
79
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 73

def build_query(action, provides, version, arch)
  hash = { "action" => action }
  hash["provides"] = provides
  add_version(hash, version) unless version.nil?
  hash["arch" ] = arch unless arch.nil?
  FFI_Yajl::Encoder.encode(hash)
end

#checkObject



52
53
54
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 52

def check
  start if stdin.nil?
end

#parse_response(output) ⇒ Object



81
82
83
84
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 81

def parse_response(output)
  array = output.split.map { |x| x == "nil" ? nil : x }
  array.each_slice(3).map { |x| Version.new(*x) }.first
end

#query(action, provides, version = nil, arch = nil) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 87

def query(action, provides, version = nil, arch = nil)
  with_helper do
    json = build_query(action, provides, version, arch)
    Chef::Log.debug "sending '#{json}' to python helper"
    stdin.syswrite json + "\n"
    output = stdout.sysread(4096).chomp
    Chef::Log.debug "got '#{output}' from python helper"
    version = parse_response(output)
    Chef::Log.debug "parsed #{version} from python helper"
    version
  end
end

#reapObject



42
43
44
45
46
47
48
49
50
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 42

def reap
  unless wait_thr.nil?
    Process.kill("KILL", wait_thr.pid) rescue nil
    stdin.close unless stdin.nil?
    stdout.close unless stdout.nil?
    stderr.close unless stderr.nil?
    wait_thr.value # this calls waitpit()
  end
end

#restartObject



100
101
102
103
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 100

def restart
  reap
  start
end

#startObject



37
38
39
40
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 37

def start
  ENV["PYTHONUNBUFFERED"] = "1"
  @stdin, @stdout, @stderr, @wait_thr = Open3.popen3(DNF_COMMAND)
end

#with_helperObject



105
106
107
108
109
110
111
112
113
114
115
# File 'lib/chef/provider/package/dnf/python_helper.rb', line 105

def with_helper
  max_retries ||= 5
  Timeout.timeout(600) do
    check
    yield
  end
rescue EOFError, Errno::EPIPE, Timeout::Error, Errno::ESRCH => e
  raise e unless ( max_retries -= 1 ) > 0
  restart
  retry
end