vmpooler-dns-gcp 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 79c98f6dafd79e083cf541e1e8893e739dee3fb34d49787f805a811daf881098
4
+ data.tar.gz: 17b710878a2714cefa44480ca3f3938a88b98be7a23bba5d43a8a504db6a2ae5
5
+ SHA512:
6
+ metadata.gz: 80a7bf801360a1cbc81363feefd0cde13f16697f390089f0f4dc3e11dedba2d03477503a09ece4460e64063ae87f135812f6b1a8eeefde5f5a01805f45b699f3
7
+ data.tar.gz: e8a4b020fc49453bcc050252106edd6c9d2792bef63f34b814d6472560295b76a0010e07db36e93bff85ce7c016c7fc4adcc3d95cc1d19501d1dff757c0b6670
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'googleauth'
4
+ require 'google/cloud/dns'
5
+ require 'vmpooler/dns/base'
6
+
7
+ module Vmpooler
8
+ class PoolManager
9
+ class Dns
10
+ # This class represent a DNS plugin to CRUD resources in Google Cloud DNS.
11
+ class Gcp < Vmpooler::PoolManager::Dns::Base
12
+ # The connection_pool method is normally used only for testing
13
+ attr_reader :connection_pool
14
+
15
+ def initialize(config, logger, metrics, redis_connection_pool, name, options)
16
+ super(config, logger, metrics, redis_connection_pool, name, options)
17
+
18
+ task_limit = global_config[:config].nil? || global_config[:config]['task_limit'].nil? ? 10 : global_config[:config]['task_limit'].to_i
19
+
20
+ default_connpool_size = [provided_pools.count, task_limit, 2].max
21
+ connpool_timeout = 60
22
+ logger.log('d', "[#{name}] ConnPool - Creating a connection pool of size #{default_connpool_size} with timeout #{connpool_timeout}")
23
+ @connection_pool = Vmpooler::PoolManager::GenericConnectionPool.new(
24
+ metrics: metrics,
25
+ connpool_type: 'dns_connection_pool',
26
+ connpool_provider: name,
27
+ size: default_connpool_size,
28
+ timeout: connpool_timeout
29
+ ) do
30
+ logger.log('d', "[#{name}] Connection Pool - Creating a connection object")
31
+ # Need to wrap the GCP connection object in another object. The generic connection pooler will preserve
32
+ # the object reference for the connection, which means it cannot "reconnect" by creating an entirely new connection
33
+ # object. Instead by wrapping it in a Hash, the Hash object reference itself never changes but the content of the
34
+ # Hash can change, and is preserved across invocations.
35
+ new_conn = connect_to_gcp
36
+ { connection: new_conn }
37
+ end
38
+ end
39
+
40
+ def name
41
+ 'gcp'
42
+ end
43
+
44
+ # main configuration options
45
+ def project
46
+ dns_config['project']
47
+ end
48
+
49
+ def zone_name
50
+ dns_config['zone_name']
51
+ end
52
+
53
+ def create_or_replace_record(hostname)
54
+ retries = 0
55
+ ip = get_ip(hostname)
56
+ if ip.nil?
57
+ debug_logger("An IP Address was not recorded for #{hostname}")
58
+ else
59
+ begin
60
+ change = connection.zone(zone_name).add(hostname, 'A', 60, ip)
61
+ debug_logger("#{change.id} - #{change.started_at} - #{change.status} DNS address added") if change
62
+ rescue Google::Cloud::AlreadyExistsError => _e
63
+ # the error is Google::Cloud::AlreadyExistsError: alreadyExists: The resource 'entity.change.additions[0]' named 'instance-8.test.vmpooler.net. (A)' already exists
64
+ # the error is Google::Cloud::AlreadyExistsError: alreadyExists: The resource 'entity.change.additions[0]' named 'instance-8.test.vmpooler.net. (A)' already exists
65
+ change = connection.zone(zone_name).replace(hostname, 'A', 60, ip)
66
+ debug_logger("#{change.id} - #{change.started_at} - #{change.status} DNS address previously existed and was replaced") if change
67
+ rescue Google::Cloud::FailedPreconditionError => e
68
+ debug_logger("DNS create failed, retrying error: #{e}")
69
+ sleep 5
70
+ retry if (retries += 1) < 30
71
+ end
72
+ end
73
+ end
74
+
75
+ def delete_record(hostname)
76
+ retries = 0
77
+ begin
78
+ connection.zone(zone_name).remove(hostname, 'A')
79
+ rescue Google::Cloud::FailedPreconditionError => e
80
+ # this error was experienced intermittently, will retry to see if it can complete successfully
81
+ # the error is Google::Cloud::FailedPreconditionError: conditionNotMet: Precondition not met for 'entity.change.deletions[1]'
82
+ debug_logger("GCP DNS delete_record failed, retrying error: #{e}")
83
+ sleep 5
84
+ retry if (retries += 1) < 30
85
+ end
86
+ end
87
+
88
+ def connection
89
+ @connection_pool.with_metrics do |pool_object|
90
+ return ensured_gcp_connection(pool_object)
91
+ end
92
+ end
93
+
94
+ def ensured_gcp_connection(connection_pool_object)
95
+ connection_pool_object[:connection] = connect_to_gcp unless gcp_connection_ok?(connection_pool_object[:connection])
96
+ connection_pool_object[:connection]
97
+ end
98
+
99
+ def gcp_connection_ok?(connection)
100
+ _result = connection.id
101
+ true
102
+ rescue StandardError
103
+ false
104
+ end
105
+
106
+ def connect_to_gcp
107
+ max_tries = global_config[:config]['max_tries'] || 3
108
+ retry_factor = global_config[:config]['retry_factor'] || 10
109
+ try = 1
110
+ begin
111
+ Google::Cloud::Dns.configure do |config|
112
+ config.project_id = project
113
+ end
114
+
115
+ dns = Google::Cloud::Dns.new
116
+
117
+ metrics.increment('connect.open')
118
+ dns
119
+ rescue StandardError => e
120
+ metrics.increment('connect.fail')
121
+ raise e if try >= max_tries
122
+
123
+ sleep(try * retry_factor)
124
+ try += 1
125
+ retry
126
+ end
127
+ end
128
+
129
+ # used in local dev environment, set DEBUG_FLAG=true
130
+ # this way the upstream vmpooler manager does not get polluted with logs
131
+ def debug_logger(message, send_to_upstream: false)
132
+ # the default logger is simple and does not enforce debug levels (the first argument)
133
+ puts message if ENV['DEBUG_FLAG']
134
+ logger.log('[g]', message) if send_to_upstream
135
+ end
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VmpoolerDnsGcp
4
+ VERSION = '1.0.0'
5
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vmpooler-dns-gcp
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Puppet by Perforce
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-04-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.16.2
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: 1.3.0
22
+ name: googleauth
23
+ prerelease: false
24
+ type: :runtime
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.16.2
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 1.3.0
33
+ - !ruby/object:Gem::Dependency
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: 0.35.1
39
+ name: google-cloud-dns
40
+ prerelease: false
41
+ type: :runtime
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.35.1
47
+ - !ruby/object:Gem::Dependency
48
+ requirement: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: '3.0'
53
+ name: vmpooler
54
+ prerelease: false
55
+ type: :runtime
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
61
+ - !ruby/object:Gem::Dependency
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 0.17.0
67
+ name: mock_redis
68
+ prerelease: false
69
+ type: :development
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 0.17.0
75
+ - !ruby/object:Gem::Dependency
76
+ requirement: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: '3.2'
81
+ name: rspec
82
+ prerelease: false
83
+ type: :development
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '3.2'
89
+ - !ruby/object:Gem::Dependency
90
+ requirement: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: 1.1.0
95
+ name: rubocop
96
+ prerelease: false
97
+ type: :development
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.1.0
103
+ - !ruby/object:Gem::Dependency
104
+ requirement: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 0.11.2
109
+ name: simplecov
110
+ prerelease: false
111
+ type: :development
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.11.2
117
+ description:
118
+ email:
119
+ executables: []
120
+ extensions: []
121
+ extra_rdoc_files: []
122
+ files:
123
+ - lib/vmpooler-dns-gcp/version.rb
124
+ - lib/vmpooler/dns/gcp.rb
125
+ homepage: https://github.com/puppetlabs/vmpooler-dns-gcp
126
+ licenses: []
127
+ metadata:
128
+ homepage_uri: https://github.com/puppetlabs/vmpooler-dns-gcp
129
+ source_code_uri: https://github.com/puppetlabs/vmpooler-dns-gcp
130
+ changelog_uri: https://github.com/puppetlabs/vmpooler-dns-gcp/blob/main/CHANGELOG.md
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: 2.3.0
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubygems_version: 3.3.25
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: Google Cloud DNS for VMPooler
150
+ test_files: []