Mercurial > repos > other > Puppet
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 |