service-bindings 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: 854eab1babdfbdaa9bb34ad78194c9225b01e0e19353866228dd475fd7856f7e
4
+ data.tar.gz: b2215de82c6b52655358f326afc8c9fe9b88b6c91f9dcd38134fe7368ac045ed
5
+ SHA512:
6
+ metadata.gz: 42acec97407aa338893b55a9e06aa56cc66de0f173b2ddbcbf3eb01e0b3d62d151306a4ac2b27c2f5997d8aa1317f520140041a9d9edc6a3a5fb51e8c39b73c3
7
+ data.tar.gz: d1d7bbdb50b3503f4799962a11b850436bf9af8d6ab186762c891a9d915f2bd63259f7282ea1afeb254735ed2e58d4fc3a9820aa6a79baed0769392ad219631d
data/.rubocop.yml ADDED
@@ -0,0 +1,22 @@
1
+ require:
2
+ - rubocop-minitest
3
+ - rubocop-rake
4
+
5
+ AllCops:
6
+ NewCops: disable
7
+ TargetRubyVersion: 3.0
8
+
9
+ Style/StringLiterals:
10
+ Enabled: true
11
+ EnforcedStyle: double_quotes
12
+
13
+ Style/StringLiteralsInInterpolation:
14
+ Enabled: true
15
+ EnforcedStyle: double_quotes
16
+
17
+ Layout/LineLength:
18
+ Max: 120
19
+
20
+ Metrics/BlockLength:
21
+ Exclude:
22
+ - "test/**/*_test.rb"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.2
@@ -0,0 +1,127 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We as members, contributors, and leaders pledge to make participation in client-ruby project and our
6
+ community a harassment-free experience for everyone, regardless of age, body
7
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
8
+ identity and expression, level of experience, education, socio-economic status,
9
+ nationality, personal appearance, race, religion, or sexual identity
10
+ and orientation.
11
+
12
+ We pledge to act and interact in ways that contribute to an open, welcoming,
13
+ diverse, inclusive, and healthy community.
14
+
15
+ ## Our Standards
16
+
17
+ Examples of behavior that contributes to a positive environment for our
18
+ community include:
19
+
20
+ * Demonstrating empathy and kindness toward other people
21
+ * Being respectful of differing opinions, viewpoints, and experiences
22
+ * Giving and gracefully accepting constructive feedback
23
+ * Accepting responsibility and apologizing to those affected by our mistakes,
24
+ and learning from the experience
25
+ * Focusing on what is best not just for us as individuals, but for the
26
+ overall community
27
+
28
+ Examples of unacceptable behavior include:
29
+
30
+ * The use of sexualized language or imagery, and sexual attention or
31
+ advances of any kind
32
+ * Trolling, insulting or derogatory comments, and personal or political attacks
33
+ * Public or private harassment
34
+ * Publishing others' private information, such as a physical or email
35
+ address, without their explicit permission
36
+ * Other conduct which could reasonably be considered inappropriate in a
37
+ professional setting
38
+
39
+ ## Enforcement Responsibilities
40
+
41
+ Community leaders are responsible for clarifying and enforcing our standards of
42
+ acceptable behavior and will take appropriate and fair corrective action in
43
+ response to any behavior that they deem inappropriate, threatening, offensive,
44
+ or harmful.
45
+
46
+ Community leaders have the right and responsibility to remove, edit, or reject
47
+ comments, commits, code, wiki edits, issues, and other contributions that are
48
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
49
+ decisions when appropriate.
50
+
51
+ ## Scope
52
+
53
+ This Code of Conduct applies within all community spaces, and also applies when
54
+ an individual is officially representing the community in public spaces.
55
+ Examples of representing our community include using an official e-mail address,
56
+ posting via an official social media account, or acting as an appointed
57
+ representative at an online or offline event.
58
+
59
+ ## Enforcement
60
+
61
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
62
+ reported to the community leaders responsible for enforcement at oss-coc@vmware.com.
63
+ All complaints will be reviewed and investigated promptly and fairly.
64
+
65
+ All community leaders are obligated to respect the privacy and security of the
66
+ reporter of any incident.
67
+
68
+ ## Enforcement Guidelines
69
+
70
+ Community leaders will follow these Community Impact Guidelines in determining
71
+ the consequences for any action they deem in violation of this Code of Conduct:
72
+
73
+ ### 1. Correction
74
+
75
+ **Community Impact**: Use of inappropriate language or other behavior deemed
76
+ unprofessional or unwelcome in the community.
77
+
78
+ **Consequence**: A private, written warning from community leaders, providing
79
+ clarity around the nature of the violation and an explanation of why the
80
+ behavior was inappropriate. A public apology may be requested.
81
+
82
+ ### 2. Warning
83
+
84
+ **Community Impact**: A violation through a single incident or series
85
+ of actions.
86
+
87
+ **Consequence**: A warning with consequences for continued behavior. No
88
+ interaction with the people involved, including unsolicited interaction with
89
+ those enforcing the Code of Conduct, for a specified period of time. This
90
+ includes avoiding interactions in community spaces as well as external channels
91
+ like social media. Violating these terms may lead to a temporary or
92
+ permanent ban.
93
+
94
+ ### 3. Temporary Ban
95
+
96
+ **Community Impact**: A serious violation of community standards, including
97
+ sustained inappropriate behavior.
98
+
99
+ **Consequence**: A temporary ban from any sort of interaction or public
100
+ communication with the community for a specified period of time. No public or
101
+ private interaction with the people involved, including unsolicited interaction
102
+ with those enforcing the Code of Conduct, is allowed during this period.
103
+ Violating these terms may lead to a permanent ban.
104
+
105
+ ### 4. Permanent Ban
106
+
107
+ **Community Impact**: Demonstrating a pattern of violation of community
108
+ standards, including sustained inappropriate behavior, harassment of an
109
+ individual, or aggression toward or disparagement of classes of individuals.
110
+
111
+ **Consequence**: A permanent ban from any sort of public interaction within
112
+ the community.
113
+
114
+ ## Attribution
115
+
116
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117
+ version 2.0, available at
118
+ https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
119
+
120
+ Community Impact Guidelines were inspired by [Mozilla's code of conduct
121
+ enforcement ladder](https://github.com/mozilla/diversity).
122
+
123
+ [homepage]: https://www.contributor-covenant.org
124
+
125
+ For answers to common questions about this code of conduct, see the FAQ at
126
+ https://www.contributor-covenant.org/faq. Translations are available at
127
+ https://www.contributor-covenant.org/translations.
data/Gemfile ADDED
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 the original author or authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ source "https://rubygems.org"
18
+
19
+ ruby "~> 3.0"
20
+
21
+ gemspec
22
+
23
+ group :development, optional: true do
24
+ gem "codecov", "~> 0.4"
25
+ gem "minitest", "~> 5.0"
26
+ gem "pg", "~> 1.0"
27
+ gem "rake", "~> 13.0"
28
+ gem "rubocop", "~> 1.7"
29
+ gem "rubocop-minitest", "~> 0.15"
30
+ gem "rubocop-rake", "~> 0.6"
31
+ gem "simplecov", "~> 0.21"
32
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ service-bindings (1.0.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ast (2.4.2)
10
+ codecov (0.6.0)
11
+ simplecov (>= 0.15, < 0.22)
12
+ docile (1.4.0)
13
+ minitest (5.14.4)
14
+ parallel (1.20.1)
15
+ parser (3.0.2.0)
16
+ ast (~> 2.4.1)
17
+ pg (1.2.3)
18
+ rainbow (3.0.0)
19
+ rake (13.0.6)
20
+ regexp_parser (2.1.1)
21
+ rexml (3.2.5)
22
+ rubocop (1.19.1)
23
+ parallel (~> 1.10)
24
+ parser (>= 3.0.0.0)
25
+ rainbow (>= 2.2.2, < 4.0)
26
+ regexp_parser (>= 1.8, < 3.0)
27
+ rexml
28
+ rubocop-ast (>= 1.9.1, < 2.0)
29
+ ruby-progressbar (~> 1.7)
30
+ unicode-display_width (>= 1.4.0, < 3.0)
31
+ rubocop-ast (1.11.0)
32
+ parser (>= 3.0.1.1)
33
+ rubocop-minitest (0.15.0)
34
+ rubocop (>= 0.90, < 2.0)
35
+ rubocop-rake (0.6.0)
36
+ rubocop (~> 1.0)
37
+ ruby-progressbar (1.11.0)
38
+ simplecov (0.21.2)
39
+ docile (~> 1.1)
40
+ simplecov-html (~> 0.11)
41
+ simplecov_json_formatter (~> 0.1)
42
+ simplecov-html (0.12.3)
43
+ simplecov_json_formatter (0.1.3)
44
+ unicode-display_width (2.0.0)
45
+
46
+ PLATFORMS
47
+ arm64-darwin-20
48
+ x86_64-linux
49
+
50
+ DEPENDENCIES
51
+ codecov (~> 0.4)
52
+ minitest (~> 5.0)
53
+ pg (~> 1.0)
54
+ rake (~> 13.0)
55
+ rubocop (~> 1.7)
56
+ rubocop-minitest (~> 0.15)
57
+ rubocop-rake (~> 0.6)
58
+ service-bindings!
59
+ simplecov (~> 0.21)
60
+
61
+ RUBY VERSION
62
+ ruby 3.0.2p107
63
+
64
+ BUNDLED WITH
65
+ 2.2.26
data/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
data/NOTICE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2021 Ben Hale
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
+ http://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.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # client-ruby
2
+
3
+ [![Tests](https://github.com/nebhale/client-ruby/workflows/Tests/badge.svg?branch=main)](https://github.com/nebhale/client-ruby/actions/workflows/tests.yaml)
4
+ [![codecov](https://codecov.io/gh/nebhale/client-ruby/branch/main/graph/badge.svg)](https://codecov.io/gh/nebhale/client-ruby)
5
+
6
+ `client-ruby` is a library to access [Service Binding Specification for Kubernetes](https://k8s-service-bindings.github.io/spec/) conformant Service Binding [Workload Projections](https://k8s-service-bindings.github.io/spec/#workload-projection).
7
+
8
+ ## Example
9
+
10
+ ```ruby
11
+ require "bindings"
12
+ require "pg"
13
+
14
+ b = Bindings.from_service_binding_root
15
+ b = Bindings.filter(b, "postgresql")
16
+ raise "Incorrect number of PostgreSQL bindings: #{b.length}" if b.length != 1
17
+
18
+ u = b[0].get("url")
19
+ raise "No URL in binding" if url.nil?
20
+
21
+ conn = PG.connect(u)
22
+
23
+ # ...
24
+ ```
25
+
26
+ ## License
27
+
28
+ Apache License v2.0: see [LICENSE](./LICENSE) for details.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "test"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["test/**/*_test.rb"]
10
+ end
11
+
12
+ require "rubocop/rake_task"
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
data/lib/binding.rb ADDED
@@ -0,0 +1,179 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 the original author or authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "secret"
18
+
19
+ # A library to access Service Binding Specification for Kubernetes conformant Service Binding Workload Projections.
20
+ #
21
+ # @see https://k8s-service-bindings.github.io/spec
22
+ module Bindings
23
+ # The key for the provider of a binding
24
+ PROVIDER = "provider"
25
+
26
+ # The key for the type of a binding
27
+ TYPE = "type"
28
+
29
+ # A representation of a binding as defined by the Kubernetes Service Binding Specification:
30
+ # https://github.com/k8s-service-bindings/spec#workload-projection
31
+ module Binding
32
+ # Returns the contents of a binding entry in its raw bytes form.
33
+ #
34
+ # @param [String] _key the key of the entry to retrieve
35
+ # @return [String] the contents of a binding entry if it exists
36
+ # @return [nil]
37
+ def get_as_bytes(_key)
38
+ raise "unimplemented"
39
+ end
40
+
41
+ # Returns the name of the binding
42
+ #
43
+ # @return [String] the name of the binding
44
+ def name
45
+ raise "unimplemented"
46
+ end
47
+
48
+ # Returns the contents of a binding entry as a UTF-8 decoded String. Any whitespace is trimmed.
49
+ #
50
+ # @param [String] key the key of the entry to retrieve
51
+ # @return [String] the contents of a binding entry as a UTF-8 decoded String if it exists
52
+ # @return [nil]
53
+ def get(key)
54
+ b = get_as_bytes(key)
55
+
56
+ return nil if b.nil?
57
+
58
+ b.pack("U*").strip
59
+ end
60
+
61
+ # Returns the value of the PROVIDER key
62
+ #
63
+ # @return [String] the value of the PROVIDER key if it exists
64
+ # @return [nil]
65
+ def provider
66
+ get(PROVIDER)
67
+ end
68
+
69
+ # Returns the value of the TYPE key.
70
+ #
71
+ # @return [String] the value of the TYPE key
72
+ def type
73
+ t = get(TYPE)
74
+
75
+ raise "binding codes not contain a type" if t.nil?
76
+
77
+ t
78
+ end
79
+ end
80
+
81
+ # An implementation of Bindings::Binding that caches values once they've been retrieved.
82
+ class CacheBinding
83
+ include Binding
84
+
85
+ # Creates a new instance.
86
+ #
87
+ # @param [Bindings::Binding] delegate the Binding used to retrieve original values
88
+ def initialize(delegate)
89
+ @delegate = delegate
90
+ @cache = {}
91
+ end
92
+
93
+ # Returns the contents of a binding entry in its raw bytes form.
94
+ #
95
+ # @param [String] key the key of the entry to retrieve
96
+ # @return [String] the contents of a binding entry if it exists
97
+ # @return [nil]
98
+ def get_as_bytes(key)
99
+ return @cache[key] if @cache.key?(key)
100
+
101
+ v = @delegate.get_as_bytes(key)
102
+ @cache[key] = v unless v.nil?
103
+
104
+ v
105
+ end
106
+
107
+ # Returns the name of the binding
108
+ #
109
+ # @return [String] the name of the binding
110
+ def name
111
+ @delegate.name
112
+ end
113
+ end
114
+
115
+ # An implementation of Bindings::Binding that reads files from a volume mounted Kubernetes Secret:
116
+ # https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets
117
+ class ConfigTreeBinding
118
+ include Binding
119
+
120
+ # Creates a new instance.
121
+ #
122
+ # @param [String] root the root of the volume mounted Kubernetes Secret
123
+ def initialize(root)
124
+ @root = root
125
+ end
126
+
127
+ # Returns the contents of a binding entry in its raw bytes form.
128
+ #
129
+ # @param [String] key the key of the entry to retrieve
130
+ # @return [Array<Integer>] the contents of a binding entry if it exists
131
+ # @return [nil]
132
+ def get_as_bytes(key)
133
+ return nil unless Bindings.valid_secret_key?(key)
134
+
135
+ p = File.join(@root, key)
136
+
137
+ return nil unless File.exist?(p) && File.file?(p)
138
+
139
+ File.read(p, mode: "rb").bytes
140
+ end
141
+
142
+ # Returns the name of the binding
143
+ #
144
+ # @return [String] the name of the binding
145
+ def name
146
+ File.basename(@root)
147
+ end
148
+ end
149
+
150
+ # An implementation of Bindings::Binding that returns values from a [Hash].
151
+ class HashBinding
152
+ include Binding
153
+
154
+ # @!attribute [r] name
155
+ # @return [String] the name of the binding
156
+ attr_reader :name
157
+
158
+ # Creates a new instance.
159
+ #
160
+ # @param [String] name the name of the binding
161
+ # @param [Hash<String, String>] content the content of the binding
162
+ def initialize(name, content)
163
+ @name = name
164
+ @content = content
165
+ end
166
+
167
+ # Returns the contents of a binding entry in its raw bytes form.
168
+ #
169
+ # @param [String] key the key of the entry to retrieve
170
+ # @return [String] the contents of a binding entry if it exists
171
+ # @return [nil]
172
+ def get_as_bytes(key)
173
+ return nil unless Bindings.valid_secret_key?(key)
174
+ return nil unless @content.key?(key)
175
+
176
+ @content[key]
177
+ end
178
+ end
179
+ end
data/lib/bindings.rb ADDED
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 the original author or authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require "binding"
18
+
19
+ # A library to access Service Binding Specification for Kubernetes conformant Service Binding Workload Projections.
20
+ #
21
+ # @see https://k8s-service-bindings.github.io/spec
22
+ module Bindings
23
+ # The name of the environment variable read to determine the bindings filesystem root. Specified by the Kubernetes
24
+ # Service Binding Specification: https://github.com/k8s-service-bindings/spec#workload-projection
25
+ SERVICE_BINDING_ROOT = "SERVICE_BINDING_ROOT"
26
+
27
+ # Wraps each Bindings::Binding in a Bindings::CacheBinding.
28
+ #
29
+ # @param [Array<Bindings::Binding>] bindings the bindings to wrap
30
+ # @return [Array<Bindings::Binding>] the wrapped bindings
31
+ def self.cached(bindings)
32
+ bindings.map { |v| Bindings::CacheBinding.new(v) }
33
+ end
34
+
35
+ # Creates a new collection of Bindings::Binding's using the specified root. If the directory does not exist, an
36
+ # empty collection is returned.
37
+ #
38
+ # @param [String] root the root to populate the bindings from
39
+ # @return [Array<Bindings::Binding>] the bindings found in the root
40
+ def self.from_path(root)
41
+ return [] unless File.exist?(root) && File.directory?(root)
42
+
43
+ Pathname.new(root).children.each_with_object([]) do |c, b|
44
+ b.append(ConfigTreeBinding.new(c.to_s)) if File.directory?(c)
45
+ end
46
+ end
47
+
48
+ # Creates a new collection of Bindings::Binding's using the +$SERVICE_BINDING_ROOT+ environment variable to determine
49
+ # system root. If the +$SERVICE_BINDING_ROOT+ environment variable is not set, an empty collection is returned. If
50
+ # the directory does not exist, an empty collection is returned.
51
+ #
52
+ # @return [Array<Bindings::Binding>] the bindings found in $SERVICE_BINDING_ROOT
53
+ def self.from_service_binding_root
54
+ return [] unless ENV.key?(SERVICE_BINDING_ROOT)
55
+
56
+ from_path(ENV[SERVICE_BINDING_ROOT])
57
+ end
58
+
59
+ # Returns a Bindings::Binding with a given name. Comparison is case-insensitive.
60
+ #
61
+ # @param [Array<Bindings::Binding>] bindings the bindings to find in
62
+ # @param [String] name the name of the binding to find
63
+ # @return [Bindings::Binding] the binding with a given name if it exists
64
+ # @return [nil]
65
+ def self.find(bindings, name)
66
+ bindings.each do |b|
67
+ return b if b.name.casecmp?(name)
68
+ end
69
+
70
+ nil
71
+ end
72
+
73
+ # Returns zero or more Bindings with a given type and provider. If type or provider are None, the result is not
74
+ # filter on that argument. Comparisons are case-insensitive.
75
+ #
76
+ # @param [Array<Bindings::Binding>] bindings the bindings to filter
77
+ # @param [String] type the type of the binding to find
78
+ # @param [nil] type
79
+ # @param [String] provider the provider of the binding to find
80
+ # @param [nil] provider
81
+ # @return [Array<Bindings::Binding>] the collection of bindings ith a given type and provider
82
+ def self.filter(bindings, type = nil, provider = nil)
83
+ match = []
84
+
85
+ bindings.each do |b|
86
+ next unless type.nil? || type_matches?(b, type)
87
+ next unless provider.nil? || provider_matches?(b, provider)
88
+
89
+ match.append(b)
90
+ end
91
+
92
+ match
93
+ end
94
+
95
+ def self.provider_matches?(binding, provider)
96
+ p = binding.provider
97
+ !p.nil? && p.casecmp?(provider)
98
+ end
99
+
100
+ def self.type_matches?(binding, type)
101
+ t = binding.type
102
+ !t.nil? && t.casecmp?(type)
103
+ end
104
+
105
+ private_class_method :provider_matches?, :type_matches?
106
+ end
data/lib/secret.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2021 the original author or authors.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ # A library to access Service Binding Specification for Kubernetes conformant Service Binding Workload Projections.
18
+ #
19
+ # @see https://k8s-service-bindings.github.io/spec
20
+ module Bindings
21
+ # Tests whether a String is a valid Kubernetes Secret key:
22
+ # https://kubernetes.io/docs/concepts/configuration/secret/#overview-of-secrets
23
+ #
24
+ # @param [String] key the key to check
25
+ # @return [boolean] true if the String is a valid Kubernetes Secret key, false otherwise
26
+ def self.valid_secret_key?(key)
27
+ /^[A-Za-z0-9\-_.]+$/.match(key)
28
+ end
29
+ end
data/sig/binding.rbs ADDED
@@ -0,0 +1,47 @@
1
+ module Bindings
2
+ PROVIDER: String
3
+
4
+ TYPE: String
5
+
6
+ module Binding
7
+ def get_as_bytes: (String key) -> Array[Integer]?
8
+
9
+ def get_name: () -> String
10
+
11
+ def get: (String key) -> String?
12
+
13
+ def get_provider: () -> String?
14
+
15
+ def get_type: () -> String
16
+ end
17
+
18
+ class CacheBinding
19
+ include Binding
20
+
21
+ def initialize: (Binding delegate) -> void
22
+
23
+ def get_as_bytes: (String key) -> Array[Integer]?
24
+
25
+ def get_name: () -> String
26
+ end
27
+
28
+ class ConfigTreeBinding
29
+ include Binding
30
+
31
+ def initialize: (String root) -> void
32
+
33
+ def get_as_bytes: (String key) -> Array[Integer]?
34
+
35
+ def get_name: () -> String
36
+ end
37
+
38
+ class HashBinding
39
+ include Binding
40
+
41
+ def initialize: (String name, Hash content) -> void
42
+
43
+ def get_as_bytes: (String key) -> Array[Integer]?
44
+
45
+ def get_name: () -> String
46
+ end
47
+ end
data/sig/bindings.rbs ADDED
@@ -0,0 +1,13 @@
1
+ module Bindings
2
+ SERVICE_BINDING_ROOT: String
3
+
4
+ def cached: (Array[Binding] bindings) -> Array[Binding]
5
+
6
+ def from_path: (String root) -> Array[Binding]
7
+
8
+ def from_service_binding_root: () -> Array[Binding]
9
+
10
+ def find: (Array[Binding] bindings, String name) -> Binding?
11
+
12
+ def filter: (Array[Binding] bindings, String? `type`, String? provider) -> Array[Binding]
13
+ end
data/sig/secret.rbs ADDED
@@ -0,0 +1,3 @@
1
+ class Object
2
+ def valid_secret_key?: (String key) -> bool
3
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: service-bindings
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Hale
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-08-25 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ - nebhale@nebhale.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - ".rubocop.yml"
21
+ - ".ruby-version"
22
+ - CODE_OF_CONDUCT.md
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - LICENSE
26
+ - NOTICE
27
+ - README.md
28
+ - Rakefile
29
+ - lib/binding.rb
30
+ - lib/bindings.rb
31
+ - lib/secret.rb
32
+ - sig/binding.rbs
33
+ - sig/bindings.rbs
34
+ - sig/secret.rbs
35
+ homepage: https://github.com/nebhale/client-ruby
36
+ licenses:
37
+ - Apache-2.0
38
+ metadata:
39
+ homepage_uri: https://github.com/nebhale/client-ruby
40
+ source_code_uri: https://github.com/nebhale/client-ruby.git
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: 3.0.0
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubygems_version: 3.2.22
57
+ signing_key:
58
+ specification_version: 4
59
+ summary: A library to access [Service Binding Specification for Kubernetes](https://k8s-service-bindings.github.io/spec/)
60
+ conformant Service Binding [Workload Projections](https://k8s-service-bindings.github.io/spec/#workload-projection)
61
+ test_files: []