comparison modules/archive/lib/puppet_x/bodeco/util.rb @ 386:3fce34f642f1

Add a PHP module to handle platform differences
author IBBoard <dev@ibboard.co.uk>
date Mon, 03 Jan 2022 17:09:39 +0000
parents
children
comparison
equal deleted inserted replaced
385:d9009f54eb23 386:3fce34f642f1
1 module PuppetX
2 module Bodeco
3 module Util
4 def self.download(url, filepath, options = {})
5 uri = URI(url)
6 @connection = PuppetX::Bodeco.const_get(uri.scheme.upcase).new("#{uri.scheme}://#{uri.host}:#{uri.port}", options)
7 @connection.download(uri, filepath)
8 end
9
10 def self.content(url, options = {})
11 uri = URI(url)
12 @connection = PuppetX::Bodeco.const_get(uri.scheme.upcase).new("#{uri.scheme}://#{uri.host}:#{uri.port}", options)
13 @connection.content(uri)
14 end
15
16 #
17 # This allows you to use a puppet syntax for a file and return its content.
18 #
19 # @example
20 # puppet_download 'puppet:///modules/my_module_name/my_file.dat
21 #
22 # @param [String] url this is the puppet url of the file to be fetched
23 # @param [String] filepath this is path of the file to create
24 #
25 # @raise [ArgumentError] when the file doesn't exist
26 #
27 def self.puppet_download(url, filepath)
28 # Somehow there is no consistent way to determine what terminus to use. So we switch to a
29 # trial and error method. First we start withe the default. And if it doesn't work, we try the
30 # other ones
31 status = load_file_with_any_terminus(url)
32 raise ArgumentError, "Previous error(s) resulted in Puppet being unable to retrieve information from environment #{Puppet['environment']} source(s) #{url}'\nMost probable cause is file not found." unless status
33 File.open(filepath, 'wb') { |file| file.write(status.content) }
34 end
35
36 # @private
37 # rubocop:disable HandleExceptions
38 def self.load_file_with_any_terminus(url)
39 termini_to_try = [:file_server, :rest]
40 termini_to_try.each do |terminus|
41 with_terminus(terminus) do
42 begin
43 content = Puppet::FileServing::Content.indirection.find(url)
44 rescue SocketError, Timeout::Error, Errno::ECONNREFUSED, Errno::EHOSTDOWN, Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Puppet::HTTP::RouteError
45 # rescue any network error
46 end
47 return content if content
48 end
49 end
50 nil
51 end
52 # rubocop:enable HandleExceptions
53
54 def self.with_terminus(terminus)
55 old_terminus = Puppet[:default_file_terminus]
56 Puppet[:default_file_terminus] = terminus
57 value = yield
58 Puppet[:default_file_terminus] = old_terminus
59 value
60 end
61 end
62 class HTTP
63 require 'net/http'
64
65 FOLLOW_LIMIT = 5
66 URI_UNSAFE = %r{[^\-_.!~*'()a-zA-Z\d;\/?:@&=+$,\[\]%]}
67
68 def initialize(_url, options)
69 @username = options[:username]
70 @password = options[:password]
71 @cookie = options[:cookie]
72 @insecure = options[:insecure]
73
74 if options[:proxy_server]
75 uri = URI(options[:proxy_server])
76 unless uri.scheme
77 uri = URI("#{options[:proxy_type]}://#{options[:proxy_server]}")
78 end
79 @proxy_addr = uri.hostname
80 @proxy_port = uri.port
81 end
82
83 ENV['SSL_CERT_FILE'] = File.expand_path(File.join(__FILE__, '..', 'cacert.pem')) if Facter.value(:osfamily) == 'windows' && !ENV.key?('SSL_CERT_FILE')
84 end
85
86 def generate_request(uri)
87 header = @cookie && { 'Cookie' => @cookie }
88
89 request = Net::HTTP::Get.new(uri.request_uri, header)
90 request.basic_auth(@username, @password) if @username && @password
91 request
92 end
93
94 def follow_redirect(uri, option = { limit: FOLLOW_LIMIT }, &block)
95 http_opts = if uri.scheme == 'https'
96 { use_ssl: true,
97 verify_mode: (@insecure ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER) }
98 else
99 { use_ssl: false }
100 end
101 Net::HTTP.start(uri.host, uri.port, @proxy_addr, @proxy_port, http_opts) do |http|
102 http.request(generate_request(uri)) do |response|
103 case response
104 when Net::HTTPSuccess
105 yield response
106 when Net::HTTPRedirection
107 limit = option[:limit] - 1
108 raise Puppet::Error, "Redirect limit exceeded, last url: #{uri}" if limit < 0
109 location = safe_escape(response['location'])
110 new_uri = URI(location)
111 new_uri = URI(uri.to_s + location) if new_uri.relative?
112 follow_redirect(new_uri, limit: limit, &block)
113 else
114 raise Puppet::Error, "HTTP Error Code #{response.code}\nURL: #{uri}\nContent:\n#{response.body}"
115 end
116 end
117 end
118 end
119
120 def download(uri, file_path, option = { limit: FOLLOW_LIMIT })
121 follow_redirect(uri, option) do |response|
122 File.open file_path, 'wb' do |io|
123 response.read_body do |chunk|
124 io.write chunk
125 end
126 end
127 end
128 end
129
130 def content(uri, option = { limit: FOLLOW_LIMIT })
131 follow_redirect(uri, option) do |response|
132 return response.body
133 end
134 end
135
136 def safe_escape(uri)
137 uri.to_s.gsub(URI_UNSAFE) do |match|
138 '%' + match.unpack('H2' * match.bytesize).join('%').upcase
139 end
140 end
141 end
142
143 class HTTPS < HTTP
144 end
145
146 class FTP
147 require 'net/ftp'
148
149 def initialize(url, options)
150 uri = URI(url)
151 username = options[:username]
152 password = options[:password]
153 proxy_server = options[:proxy_server]
154 proxy_type = options[:proxy_type]
155
156 ENV["#{proxy_type}_proxy"] = proxy_server
157
158 @ftp = Net::FTP.new
159 @ftp.connect(uri.host, uri.port)
160 if username
161 @ftp.login(username, password)
162 else
163 @ftp.login
164 end
165 end
166
167 def download(uri, file_path)
168 @ftp.getbinaryfile(uri.path, file_path)
169 end
170 end
171
172 class FILE
173 def initialize(_url, _options) end
174
175 def download(uri, file_path)
176 FileUtils.copy(uri.path, file_path)
177 end
178 end
179 end
180 end