google-cloud-spanner 2.10.1 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0beabc13ee4d11f2c6c0cc632bcf78359fc6e9d090ae53beed550fd86409feca
4
- data.tar.gz: c24820a5fafff86d5a668df2715ae6b81420fab10a4aea60654c48ae0456a502
3
+ metadata.gz: 18756346d168b932d199c46b4d4cdecfadb95949f033d03da083ed0b4527ab3a
4
+ data.tar.gz: 4adaf5992dc2be079f2b6d82bb5adc55b09b91af496b4651f0ba7e4eca784c9f
5
5
  SHA512:
6
- metadata.gz: 4322a66151a30d42daaecbedbf3a49e78ca80b34d3c991f196beb2af3293ae173ce99ce7e49338e383dbe6da29c2ec9877c94e3ed6973d6935da07421bcdee61
7
- data.tar.gz: d78c1bc68027481ddc8674a958df3e32a93191618829aa9a16fa87fb9d407d49c8243c9482fc07e39022d2c54144a6edc98d2934bde4736a7a276ed669e2d645
6
+ metadata.gz: 7e6bcb561edc3b947af1b7ce426b59483692a08566b50bd1bfe4e7a6c2174f26183fc42e830589201278e7af7af4563f14ca06f53251d4db27386d2c98fad712
7
+ data.tar.gz: 343a05ccc2f546fd99a2a9b759db7cce6903d40e60a71c800abf7cb00543be3cc35250b7dec1365ee424f0dca3d479b2105282de5091caeee8760f80ce0fc5b8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Release History
2
2
 
3
+ ### 2.11.0 / 2021-12-10
4
+
5
+ #### Features
6
+
7
+ * add admin instance wrapper ([#16080](https://www.github.com/googleapis/google-cloud-ruby/issues/16080))
8
+ * Updated benchwrapper and proto for spanner. ([#16152](https://www.github.com/googleapis/google-cloud-ruby/issues/16152))
9
+ * use gRPC clients for instance/database management ([#13157](https://www.github.com/googleapis/google-cloud-ruby/issues/13157))
10
+ * wrapper to create generated admin database client. ([#13456](https://www.github.com/googleapis/google-cloud-ruby/issues/13456))
11
+
3
12
  ### 2.10.1 / 2021-11-09
4
13
 
5
14
  #### Documentation
data/OVERVIEW.md CHANGED
@@ -23,29 +23,36 @@ create an instance, you choose where your data is stored and how many nodes are
23
23
  used for your data. (For more information, see [Configuration
24
24
  Guide](https://googleapis.dev/ruby/stackdriver/latest/file.INSTRUMENTATION_CONFIGURATION.html).
25
25
 
26
- Use {Google::Cloud::Spanner::Project#create_instance Project#create_instance} to
27
- create an instance:
26
+ Use {Google::Cloud::Spanner::Admin::Instance#instance_admin
27
+ Client#create_instance} to create an instance:
28
28
 
29
29
  ```ruby
30
30
  require "google/cloud/spanner"
31
31
 
32
- spanner = Google::Cloud::Spanner.new
33
-
34
- job = spanner.create_instance "my-instance",
35
- name: "My Instance",
36
- config: "regional-us-central1",
37
- nodes: 5,
38
- labels: { production: :env }
39
-
40
- job.done? #=> false
41
- job.reload! # API call
42
- job.done? #=> true
43
-
44
- if job.error?
45
- status = job.error
46
- else
47
- instance = job.instance
48
- end
32
+ instance_admin_client = \
33
+ Google::Cloud::Spanner::Admin::Instance.instance_admin project_id: "my-project"
34
+
35
+ project_path = \
36
+ instance_admin_client.project_path project: "my-project"
37
+ config_path = \
38
+ instance_admin_client.instance_config_path project: "my-project",
39
+ instance_config: "regional-us-central1"
40
+ instance_path = \
41
+ instance_admin_client.instance_path project: "my-project",
42
+ instance: "my-instance"
43
+
44
+ job = instance_admin_client.create_instance parent: project_path,
45
+ instance_id: "my-instance",
46
+ instance: Google::Cloud::Spanner::Admin::Instance::V1::Instance.new({
47
+ name: instance_path
48
+ display_name: "My Instance",
49
+ config: config_path,
50
+ node_count: 5,
51
+ labels: { "production": :env }
52
+ })
53
+
54
+ job.wait_until_done!
55
+ instance = job.results
49
56
  ```
50
57
 
51
58
  ## Creating databases
@@ -54,26 +61,23 @@ Now that you have created an instance, you can create a database. Cloud
54
61
  Spanner databases hold the tables and indexes that allow you to read and
55
62
  write data. You may create multiple databases in an instance.
56
63
 
57
- Use {Google::Cloud::Spanner::Project#create_database Project#create_database}
58
- (or {Google::Cloud::Spanner::Instance#create_database Instance#create_database})
59
- to create a database:
64
+ Use {Google::Cloud::Spanner::Admin::Database#database_admin
65
+ Client#create_database} to create a database:
60
66
 
61
67
  ```ruby
62
68
  require "google/cloud/spanner"
63
69
 
64
- spanner = Google::Cloud::Spanner.new
70
+ db_admin_client = \
71
+ Google::Cloud::Spanner::Admin::Database.database_admin project_id: "my-project"
65
72
 
66
- job = spanner.create_database "my-instance", "my-database"
73
+ instance_path = \
74
+ db_admin_client.instance_path project: "my-project", instance: "my-instance"
67
75
 
68
- job.done? #=> false
69
- job.reload! # API call
70
- job.done? #=> true
76
+ job = db_admin_client.create_database parent: instance_path,
77
+ create_statement: "CREATE DATABASE my-database",
71
78
 
72
- if job.error?
73
- status = job.error
74
- else
75
- database = job.database
76
- end
79
+ job.wait_until_done!
80
+ database = job.results
77
81
  ```
78
82
 
79
83
  ## Updating database schemas
@@ -83,16 +87,19 @@ continues to serve traffic. Schema updates do not require taking the
83
87
  database offline and they do not lock entire tables or columns; you can
84
88
  continue writing data to the database during the schema update.
85
89
 
86
- Use {Google::Cloud::Spanner::Database#update Database#update} to execute one or
87
- more statements in Cloud Spanner's Data Definition Language (DDL):
90
+ Use {Google::Cloud::Spanner::Admin::Database#database_admin
91
+ Client#update_database_ddl} to execute one or more statements in Cloud Spanner's
92
+ Data Definition Language (DDL):
88
93
 
89
94
  ```ruby
90
95
  require "google/cloud/spanner"
91
96
 
92
- spanner = Google::Cloud::Spanner.new
93
-
94
- database = spanner.database "my-instance", "my-database"
97
+ db_admin_client = \
98
+ Google::Cloud::Spanner::Admin::Database.database_admin project_id: "my-project"
95
99
 
100
+ db_path = db_admin_client.database_path project: "my-project",
101
+ instance: "my-instance",
102
+ database: "my-database"
96
103
  add_users_table_sql = %q(
97
104
  CREATE TABLE users (
98
105
  id INT64 NOT NULL,
@@ -102,13 +109,17 @@ add_users_table_sql = %q(
102
109
  ) PRIMARY KEY(id)
103
110
  )
104
111
 
105
- database.update statements: [add_users_table_sql]
112
+ job = db_admin_client.update_database_ddl database: db_path,
113
+ statements: [add_users_table_sql]
114
+
115
+ job.wait_until_done!
116
+ database = job.results
106
117
  ```
107
118
 
108
119
  ## Creating clients
109
120
 
110
- In order to read and/or write data, you must create a database client. You can
111
- think of a client as a database connection: All of your interactions with Cloud
121
+ In order to read and/or write data, you must create a data client. You can think
122
+ of a client as a database connection: All of your interactions with Cloud
112
123
  Spanner data must go through a client. Typically you create a client when your
113
124
  application starts up, then you re-use that client to read, write, and execute
114
125
  transactions.
@@ -289,33 +300,41 @@ end
289
300
 
290
301
  ## Deleting databases
291
302
 
292
- Use {Google::Cloud::Spanner::Database#drop Database#drop} to delete a database:
303
+ Use {Google::Cloud::Spanner::Admin::Database#database_admin
304
+ Client#drop_database} to delete a database:
293
305
 
294
306
  ```ruby
295
307
  require "google/cloud/spanner"
296
308
 
297
- spanner = Google::Cloud::Spanner.new
309
+ db_admin_client = \
310
+ Google::Cloud::Spanner::Admin::Database.database_admin project_id: "my-project"
298
311
 
299
- database = spanner.database "my-instance", "my-database"
300
-
301
- database.drop
312
+ db_path = db_admin_client.database_path project: "my-project",
313
+ instance: "my-instance",
314
+ database: "my-database"
315
+ db_admin_client.drop_database database: db_path
302
316
  ```
303
317
 
304
318
  ## Deleting instances
305
319
 
306
320
  When you delete an instance, all databases within it are automatically deleted.
307
321
  (If you only delete databases and not your instance, you will still incur
308
- charges for the instance.) Use {Google::Cloud::Spanner::Instance#delete
309
- Instance#delete} to delete an instance:
322
+ charges for the instance.)
323
+
324
+ Use {Google::Cloud::Spanner::Admin::Instance#instance_admin
325
+ Client#delete_instance} to delete an instance:
310
326
 
311
327
  ```ruby
312
328
  require "google/cloud/spanner"
313
329
 
314
- spanner = Google::Cloud::Spanner.new
330
+ instance_admin_client = \
331
+ Google::Cloud::Spanner::Admin::Instance.instance_admin project_id: "my-project"
315
332
 
316
- instance = spanner.instance "my-instance"
333
+ instance_path = \
334
+ instance_admin_client.instance_path project: "my-project",
335
+ instance: "my-instance"
317
336
 
318
- instance.delete
337
+ instance_admin_client.delete_instance name: instance_path
319
338
  ```
320
339
 
321
340
  ## Additional information
@@ -0,0 +1,321 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require "google-cloud-spanner"
16
+ require "google/cloud/config"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Spanner
21
+ module Admin
22
+ module Database
23
+ ##
24
+ # Create a new client object for a DatabaseAdmin.
25
+ #
26
+ # This returns an instance of
27
+ # [Google::Cloud::Spanner::Admin::Database::V1::DatabaseAdmin::Client](https://googleapis.dev/ruby/google-cloud-spanner-admin-database-v1/latest/Google/Cloud/Spanner/Admin/Database/V1/DatabaseAdmin/Client.html)
28
+ # for version V1 of the API.
29
+ #
30
+ # ## About DatabaseAdmin
31
+ #
32
+ # Google Cloud Spanner Database Admin Service
33
+ #
34
+ # The Cloud Spanner Database Admin API can be used to create, drop, and
35
+ # list databases. It also enables updating the schema of pre-existing
36
+ # databases. It can be also used to create, delete and list backups for a
37
+ # database and to restore from an existing backup.
38
+ #
39
+ # For more information on connecting to Google Cloud see the
40
+ # {file:AUTHENTICATION.md Authentication Guide}.
41
+ #
42
+ # @param [String] project_id Project identifier for the Spanner service
43
+ # you are connecting to. If not present, the default project for the
44
+ # credentials is used.
45
+ # @param [String, Hash, Google::Auth::Credentials] credentials The path to
46
+ # the keyfile as a String, the contents of the keyfile as a Hash, or a
47
+ # Google::Auth::Credentials object. (See {Spanner::Credentials})
48
+ # If `emulator_host` is present, this becomes optional and the value is
49
+ # internally overriden with `:this_channel_is_insecure`.
50
+ # @param [String, Array<String>] scope The OAuth 2.0 scopes controlling
51
+ # the set of resources and operations that the connection can access.
52
+ # See [Using OAuth 2.0 to Access Google
53
+ # APIs](https://developers.google.com/identity/protocols/OAuth2).
54
+ #
55
+ # The default scopes are:
56
+ #
57
+ # * `https://www.googleapis.com/auth/spanner`
58
+ # * `https://www.googleapis.com/auth/spanner.data`
59
+ # @param [Integer] timeout Default timeout to use in requests. Optional.
60
+ # @param [String] endpoint Override of the endpoint host name. Optional.
61
+ # If the param is nil, uses `emulator_host` or the default endpoint.
62
+ # @param [String] project Alias for the `project_id` argument. Deprecated.
63
+ # @param [String] keyfile Alias for the `credentials` argument.
64
+ # Deprecated.
65
+ # @param [String] emulator_host Spanner emulator host. Optional.
66
+ # If the param is nil, uses the value of the `emulator_host` config.
67
+ # @param [String] lib_name Library name. This will be added as a prefix
68
+ # to the API call tracking header `x-goog-api-client` with provided
69
+ # lib version for telemetry. Optional. For example prefix looks like
70
+ # `spanner-activerecord/0.0.1 gccl/1.13.1`. Here,
71
+ # `spanner-activerecord/0.0.1` is provided custom library name and
72
+ # version and `gccl/1.13.1` represents the Cloud Spanner Ruby library
73
+ # with version.
74
+ # @param [String] lib_version Library version. This will be added as a
75
+ # prefix to the API call tracking header `x-goog-api-client` with
76
+ # provided lib name for telemetry. Optional. For example prefix look like
77
+ # `spanner-activerecord/0.0.1 gccl/1.13.1`. Here,
78
+ # `spanner-activerecord/0.0.1` is provided custom library name and
79
+ # version and `gccl/1.13.1` represents the Cloud Spanner Ruby library
80
+ # with version.
81
+ #
82
+ # @return [Admin::Database::V1::DatabaseAdmin::Client] A client object of version V1.
83
+ #
84
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
85
+ def self.database_admin project_id: nil,
86
+ credentials: nil,
87
+ scope: nil,
88
+ timeout: nil,
89
+ endpoint: nil,
90
+ project: nil,
91
+ keyfile: nil,
92
+ emulator_host: nil,
93
+ lib_name: nil,
94
+ lib_version: nil
95
+ project_id ||= project || default_project_id
96
+ scope ||= configure.scope
97
+ timeout ||= configure.timeout
98
+ emulator_host ||= configure.emulator_host
99
+ endpoint ||= emulator_host || configure.endpoint
100
+ credentials ||= keyfile
101
+ lib_name ||= configure.lib_name
102
+ lib_version ||= configure.lib_version
103
+
104
+ if emulator_host
105
+ credentials = :this_channel_is_insecure
106
+ else
107
+ credentials ||= default_credentials scope: scope
108
+ unless credentials.is_a? Google::Auth::Credentials
109
+ credentials = Spanner::Credentials.new credentials, scope: scope
110
+ end
111
+
112
+ if credentials.respond_to? :project_id
113
+ project_id ||= credentials.project_id
114
+ end
115
+ end
116
+
117
+ project_id = project_id.to_s # Always cast to a string
118
+ raise ArgumentError, "project_id is missing" if project_id.empty?
119
+
120
+ Admin::Database::V1::DatabaseAdmin::Client.new do |config|
121
+ config.credentials = channel endpoint, credentials
122
+ config.timeout = timeout if timeout
123
+ config.endpoint = endpoint if endpoint
124
+ config.lib_name = lib_name_with_prefix lib_name, lib_version
125
+ config.lib_version = Google::Cloud::Spanner::VERSION
126
+ config.metadata = { "google-cloud-resource-prefix" => "projects/#{project_id}" }
127
+ end
128
+ end
129
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
130
+
131
+ ##
132
+ # Configure the Google Cloud Spanner Database Admin library. This configuration can be
133
+ # applied globally to all clients.
134
+ #
135
+ # @example
136
+ #
137
+ # Modify the global config, setting the timeout to 10 seconds for all admin databases.
138
+ #
139
+ # require "google/cloud/spanner/admin/database"
140
+ #
141
+ # ::Google::Cloud::Spanner::Admin::Database.configure do |config|
142
+ # config.timeout = 10.0
143
+ # end
144
+ #
145
+ # The following configuration parameters are supported:
146
+ #
147
+ # * `credentials` (*type:* `String, Hash, Google::Auth::Credentials`) -
148
+ # The path to the keyfile as a String, the contents of the keyfile as a
149
+ # Hash, or a Google::Auth::Credentials object.
150
+ # * `lib_name` (*type:* `String`) -
151
+ # The library name as recorded in instrumentation and logging.
152
+ # * `lib_version` (*type:* `String`) -
153
+ # The library version as recorded in instrumentation and logging.
154
+ # * `interceptors` (*type:* `Array<GRPC::ClientInterceptor>`) -
155
+ # An array of interceptors that are run before calls are executed.
156
+ # * `timeout` (*type:* `Numeric`) -
157
+ # Default timeout in seconds.
158
+ # * `emulator_host` - (String) Host name of the emulator. Defaults to
159
+ # `ENV["SPANNER_EMULATOR_HOST"]`.
160
+ # * `metadata` (*type:* `Hash{Symbol=>String}`) -
161
+ # Additional gRPC headers to be sent with the call.
162
+ # * `retry_policy` (*type:* `Hash`) -
163
+ # The retry policy. The value is a hash with the following keys:
164
+ # * `:initial_delay` (*type:* `Numeric`) - The initial delay in seconds.
165
+ # * `:max_delay` (*type:* `Numeric`) - The max delay in seconds.
166
+ # * `:multiplier` (*type:* `Numeric`) - The incremental backoff multiplier.
167
+ # * `:retry_codes` (*type:* `Array<String>`) -
168
+ # The error codes that should trigger a retry.
169
+ #
170
+ # @return [::Google::Cloud::Config] The default configuration used by this library
171
+ #
172
+ def self.configure
173
+ @configure ||= begin
174
+ namespace = ["Google", "Cloud", "Spanner"]
175
+ parent_config = while namespace.any?
176
+ parent_name = namespace.join "::"
177
+ parent_const = const_get parent_name
178
+ break parent_const.configure if parent_const.respond_to? :configure
179
+ namespace.pop
180
+ end
181
+
182
+ default_config = Database::Configuration.new parent_config
183
+ default_config
184
+ end
185
+ yield @configure if block_given?
186
+ @configure
187
+ end
188
+
189
+ ##
190
+ # @private Default project.
191
+ def self.default_project_id
192
+ Google::Cloud.configure.spanner.project_id ||
193
+ Google::Cloud.configure.project_id ||
194
+ Google::Cloud.env.project_id
195
+ end
196
+
197
+ ##
198
+ # @private Default credentials.
199
+ def self.default_credentials scope: nil
200
+ Google::Cloud.configure.spanner.credentials ||
201
+ Google::Cloud.configure.credentials ||
202
+ Spanner::Credentials.default(scope: scope)
203
+ end
204
+
205
+ ##
206
+ # @private gRPC channel.
207
+ def self.channel host, credentials
208
+ require "grpc"
209
+ GRPC::Core::Channel.new host, chan_args, chan_creds(credentials)
210
+ end
211
+
212
+ ##
213
+ # @private gRPC channel args.
214
+ def self.chan_args
215
+ { "grpc.service_config_disable_resolution" => 1 }
216
+ end
217
+
218
+ ##
219
+ # @private gRPC channel credentials
220
+ def self.chan_creds credentials
221
+ return credentials if credentials == :this_channel_is_insecure
222
+ require "grpc"
223
+ GRPC::Core::ChannelCredentials.new.compose \
224
+ GRPC::Core::CallCredentials.new credentials.client.updater_proc
225
+ end
226
+
227
+ ##
228
+ # @private Spanner client library version with the prefix.
229
+ def self.lib_name_with_prefix lib_name, lib_version
230
+ return "gccl" if [nil, "gccl"].include? lib_name
231
+
232
+ value = lib_name.dup
233
+ value << "/#{lib_version}" if lib_version
234
+ value << " gccl"
235
+ end
236
+
237
+ ##
238
+ # Configuration class for the Spanner Admin Database.
239
+ #
240
+ # This class provides control over timeouts, retry behavior,
241
+ # query options, and other low-level controls.
242
+ #
243
+ # @!attribute [rw] endpoint
244
+ # The hostname or hostname:port of the service endpoint.
245
+ # Defaults to `"spanner.googleapis.com"`.
246
+ # @return [::String]
247
+ # @!attribute [rw] credentials
248
+ # Credentials to send with calls. You may provide any of the following types:
249
+ # * (`String`) The path to a service account key file in JSON format
250
+ # * (`Hash`) A service account key as a Hash
251
+ # * (`Google::Auth::Credentials`) A googleauth credentials object
252
+ # (see the [googleauth docs](https://googleapis.dev/ruby/googleauth/latest/index.html))
253
+ # * (`Signet::OAuth2::Client`) A signet oauth2 client object
254
+ # (see the [signet docs](https://googleapis.dev/ruby/signet/latest/Signet/OAuth2/Client.html))
255
+ # * (`GRPC::Core::Channel`) a gRPC channel with included credentials
256
+ # * (`GRPC::Core::ChannelCredentials`) a gRPC credentails object
257
+ # * (`nil`) indicating no credentials
258
+ # @return [::Object]
259
+ # @!attribute [rw] scope
260
+ # The OAuth scopes
261
+ # @return [::Array<::String>]
262
+ # @!attribute [rw] lib_name
263
+ # The library name as recorded in instrumentation and logging
264
+ # @return [::String]
265
+ # @!attribute [rw] lib_version
266
+ # The library version as recorded in instrumentation and logging
267
+ # @return [::String]
268
+ # @!attribute [rw] interceptors
269
+ # An array of interceptors that are run before calls are executed.
270
+ # @return [::Array<::GRPC::ClientInterceptor>]
271
+ # @!attribute [rw] timeout
272
+ # The call timeout in seconds.
273
+ # @return [::Numeric]
274
+ # @!attribute [rw] metadata
275
+ # Additional gRPC headers to be sent with the call.
276
+ # @return [::Hash{::Symbol=>::String}]
277
+ # @!attribute [rw] retry_policy
278
+ # The retry policy. The value is a hash with the following keys:
279
+ # * `:initial_delay` (*type:* `Numeric`) - The initial delay in seconds.
280
+ # * `:max_delay` (*type:* `Numeric`) - The max delay in seconds.
281
+ # * `:multiplier` (*type:* `Numeric`) - The incremental backoff multiplier.
282
+ # * `:retry_codes` (*type:* `Array<String>`) - The error codes that should
283
+ # trigger a retry.
284
+ # @return [::Hash]
285
+ # @!attribute [rw] quota_project
286
+ # A separate project against which to charge quota.
287
+ # @return [::String]
288
+ #
289
+ class Configuration
290
+ extend ::Gapic::Config
291
+
292
+ config_attr :endpoint, "spanner.googleapis.com", ::String
293
+ config_attr :credentials, nil do |value|
294
+ allowed = [::String, ::Hash, ::Google::Auth::Credentials, ::Signet::OAuth2::Client, nil]
295
+ allowed += [::GRPC::Core::Channel, ::GRPC::Core::ChannelCredentials] if defined? ::GRPC
296
+ allowed.any? { |klass| klass === value }
297
+ end
298
+ config_attr :project_id, nil, ::String, nil
299
+ config_attr :scope, nil, ::String, ::Array, nil
300
+ config_attr :lib_name, nil, ::String, nil
301
+ config_attr :lib_version, nil, ::String, nil
302
+ config_attr :interceptors, nil, ::Array, nil
303
+ config_attr :timeout, nil, ::Numeric, nil
304
+ config_attr :quota_project, nil, ::String, nil
305
+ config_attr :emulator_host, nil, ::String, nil
306
+ config_attr :query_options, nil, ::Hash, nil
307
+ config_attr :metadata, nil, ::Hash, nil
308
+ config_attr :retry_policy, nil, ::Hash, nil
309
+
310
+ # @private
311
+ def initialize parent_config = nil
312
+ @parent_config = parent_config unless parent_config.nil?
313
+
314
+ yield self if block_given?
315
+ end
316
+ end
317
+ end
318
+ end
319
+ end
320
+ end
321
+ end