launchdarkly_api_helper 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 48a1fa66d19b0af509741df158d57e04cbcd379e1cc0f921bd8755bfd2b8bfd6
4
- data.tar.gz: 10fe7dcfb0fe90a797f874b56c2f99deecc0e69028e7d58fbd69c84f5b1e41b4
3
+ metadata.gz: f063313104693353f6dd3e18a6ecd69c5142b62eb3f072b08f96b8b51e9175e0
4
+ data.tar.gz: 1f83a4dc6665e8864605decdb1d265178232785d44cca584488533fe21bd4ce6
5
5
  SHA512:
6
- metadata.gz: 1349639032b66a4091b84d0188d0b5935dd5758aa5ab4eede29c57312972d57b1b648988dc135ceba8b82fd4c8425d451235436f7723b85da54945dcb8dc0ff4
7
- data.tar.gz: b1de7f7890f2f68d19b31936b789670aefab91b259676f5c2aa26d6aa093156fa0f9a13950640e95451d9f9153aa7180f7930818d9099a37c0317ab9c47eb327
6
+ metadata.gz: e9fadbf1588e1d429f3cf3d1bf9bcccf6b06bda032baa707970a65714321a970e8e5d8f952baa99be5115e4986564c45bbcfcc07034f829637522569e5fd9f15
7
+ data.tar.gz: b947d46ef24947acba122a57ce2e2c582af6342806e357de59864523ba4b8e78e9d81185dc6f51d4b183621d94b97d206840d020dc5226731db866ef77a25c7a
data/.rubocop.yml CHANGED
@@ -9,12 +9,21 @@ Style/StringLiteralsInInterpolation:
9
9
  Enabled: true
10
10
  EnforcedStyle: double_quotes
11
11
 
12
+ Style/OptionalBooleanParameter:
13
+ Enabled: false
14
+
12
15
  Layout/LineLength:
13
16
  Max: 120
14
17
 
15
18
  Metrics/MethodLength:
16
19
  Max: 100
17
20
 
21
+ Metrics/MethodName:
22
+ Max: 100
23
+
24
+ Metrics/ClassLength:
25
+ Max: 150
26
+
18
27
  Metrics/AbcSize:
19
28
  Enabled: false
20
29
 
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # LaunchdarklyApiHelper
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/launchdarkly_api_helper`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [LaunchDarklyApiHelper](https://rubygems.org/gems/launchdarkly_api_helper) provides you a way to access your [Launch Darkly](https://apidocs.launchdarkly.com/) account using [API token](https://app.launchdarkly.com/settings/authorization/tokens/new) to view, edit or delete them accordingly.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ![alt text](https://docs.launchdarkly.com/static/de107a76f0cd388da14d5bd650ec1f5c/b8471/settings-access-tokens-obscured-callout.png)
6
+
7
+ [Launch Darkly API Documentation](https://apidocs.launchdarkly.com/)
6
8
 
7
9
  ## Installation
8
10
 
@@ -16,7 +18,193 @@ If bundler is not being used to manage dependencies, install the gem by executin
16
18
 
17
19
  ## Usage
18
20
 
19
- TODO: Write usage instructions here
21
+ add `require 'launchdarkly_api_helper'` line at the beginning of your Ruby file
22
+
23
+ add `include LaunchdarklyApiHelper` line to access LaunchdarklyApiHelper module in gem _launchdarkly_api_helper_
24
+
25
+ To perform any operations such as add, remove, replace, move, copy, test you should have a working knowledge of [JSON Patch](https://datatracker.ietf.org/doc/html/rfc6902)
26
+
27
+ ```ruby
28
+ parameters:
29
+ access_token (*required): this token will be used to send all requests to LaunchDarkly (string)
30
+ log_file: all logs will be writeen to file 'launchdarkly.log' by default if no file name specified
31
+
32
+ # set your LD API token and log file to capture logs
33
+ def ld_access_token(access_token, log_file = 'launchdarkly.log')
34
+ # code ...
35
+ end
36
+ ```
37
+
38
+ [Get feature flag](https://apidocs.launchdarkly.com/tag/Feature-flags#operation/getFeatureFlag)
39
+
40
+ ```ruby
41
+ GET REQUEST
42
+ https://app.launchdarkly.com/api/v2/flags/default/developer_flag_for_regression
43
+
44
+ parameters:
45
+ env (*required): name of the environment for which you want to get the details (string)
46
+ flag (*required): name of the feature flag for which you want to get the details (string)
47
+
48
+ Here, 'developer_flag_for_regression' is the feature flag name and default is our Project name - eg. AmitSinghBisht
49
+ By default, this returns the configurations for all environments
50
+ You can filter environments with the env query parameter. For example, setting env=staging restricts the returned configurations to just the staging environment
51
+ https://app.launchdarkly.com/api/v2/flags/default/developer_flag_for_regression?env=staging
52
+
53
+ # this method will give you entire details about a flag for that particular environment
54
+ def ld_fetch_flag_details(env, flag)
55
+ # code ...
56
+ end
57
+
58
+ @return value (response of feature flag details):
59
+ response = "https://app.launchdarkly.com/api/v2/flags/default/#{flag}?env=#{env}" (string)
60
+ ```
61
+
62
+ ```ruby
63
+ Get toggle status feature flag
64
+
65
+ parameters:
66
+ env (*required): name of the environment for which you want to get the details (string)
67
+ flag (*required): name of the feature flag for which you want to get the details (string)
68
+
69
+ response = https://app.launchdarkly.com/api/v2/flags/default/developer_flag_for_regression?env=staging
70
+ grab the value of the ['environments'][env]['on'] obtained from the above response
71
+
72
+ # this method will return the status of the flag, whether it is on or off viz set to true or false
73
+ def ld_fetch_flag_toggle_status(env, flag)
74
+ # code ...
75
+ end
76
+
77
+ @return value (response of feature flag toggle status):
78
+ response = "https://app.launchdarkly.com/api/v2/flags/default/#{flag}?env=#{env}"
79
+ response['environments'][env]['on'] (boolean)
80
+ ```
81
+
82
+ ```ruby
83
+ Create a feature flag
84
+ https://apidocs.launchdarkly.com/tag/Feature-flags/#operation/postFeatureFlag
85
+
86
+ POST REQUEST
87
+ https://app.launchdarkly.com/api/v2/flags/default
88
+
89
+ Here, default is our Project name - eg. AmitSinghBisht
90
+
91
+ parameters:
92
+ key (*required): A unique key used to reference the feature flag in your code (string)
93
+ name (*required): A human-friendly name for the feature flag (string)
94
+ description: Description of the feature flag. Defaults to an empty string (string)
95
+ tags: Tags for the feature flag. Defaults to an empty array (Array of strings)
96
+ variations: An array of possible variations for the flag. The variation values must be unique. If omitted, two boolean variations of true and false will be used (Array of objects)
97
+
98
+ defaults
99
+ * onVariation (*required): The index, from the array of variations for this flag, of the variation to serve by default when targeting is on (integer)
100
+ * offVariation (*required): The index, from the array of variations for this flag, of the variation to serve by default when targeting is off (integer)
101
+
102
+ {
103
+ "key": "developer_flag_for_regression",
104
+ "name": "developer_flag_for_regression",
105
+ "description": "developer_flag_for_regression is created via regression api on 18_10_2022",
106
+ "tags": [
107
+ "created_via_regression_api_on_18_10_2022"
108
+ ],
109
+ "variations": [
110
+ {
111
+ "age": 10
112
+ },
113
+ {
114
+ "age": 20
115
+ }
116
+ ],
117
+ "defaults": {
118
+ "onVariation": 1,
119
+ "offVariation": 0
120
+ }
121
+ }
122
+
123
+ Above code will create a key 'developer_flag_for_regression' with name as 'developer_flag_for_regression' and description as 'developer_flag_for_regression is created via regression api on 18_10_2022'
124
+
125
+ Variations are provided while creating key, by default variation is a boolean value (true and false). once flag with a specific variation is created, its type cannot be modified later, hence choose your variation type smartly (Boolean, String, Number, JSON) In above example we are creating a flag with JSON type and its two values are 'age': 10 and 'age': 20
126
+
127
+ Also, variation has by default two values, and you must also define two variations while creating your own custom feature flag
128
+
129
+ Default will specify which variation to serve when flag is on or off. In above example when flag is turned on, '1' variation is served [Note: 0 and 1 are index position], so variations at first index ie variations[1] will be served when flag is turned on ie 'age': 20
130
+
131
+ # this method will create a new feature flag, NOTE: feature falg are created at global level and environment resides inside feature flag
132
+ def ld_create_flag(key, name = key, description = key, tags = ['created_via_regression_api'])
133
+ # code ...
134
+ end
135
+ ```
136
+
137
+ ```ruby
138
+ Update feature flag
139
+ https://apidocs.launchdarkly.com/tag/Feature-flags#operation/patchFeatureFlag
140
+
141
+ PATCH REQUEST
142
+ https://app.launchdarkly.com/api/v2/flags/default/developer_flag_for_regression
143
+
144
+ parameters:
145
+ env (*required): name of the environment for which you want to get the details (string)
146
+ flag (*required): name of the feature flag for which you want to get the details (string)
147
+ flag_value: status of the feature flag that you want to set either on (true) or off (false) (boolean)
148
+
149
+ Here, 'developer_flag_for_regression' is the flag key and default is our Project name - eg. AmitSinghBisht
150
+ You can update any parameter of feature flag using this method
151
+
152
+ # this method will be used to toggle status of feature flag either on / off for a particular environment
153
+ def ld_toggle_specific_environment(env, flag, flag_value = true)
154
+ # code ...
155
+ end
156
+
157
+ @return value (response of feature flag toggle status):
158
+ response = "https://app.launchdarkly.com/api/v2/flags/default/#{flag}?env=#{env}"
159
+ response['environments'][env]['on'] (boolean)
160
+ ```
161
+
162
+ ```ruby
163
+ Get status of feature flag
164
+ https://apidocs.launchdarkly.com/tag/Feature-flags#operation/patchFeatureFlag
165
+
166
+ def ld_toggle_variation_served(env, flag)
167
+ # code ...
168
+ end
169
+
170
+ @returns: [fetch_flag_toggle_status_response, feature_flag_variation_index_response, feature_flag_variation_value_response, feature_flag_variation_name_response]
171
+ @return parameter:
172
+ response = "https://app.launchdarkly.com/api/v2/flags/default/#{flag}?env=#{env}"
173
+ fetch_flag_toggle_status_response: response['environments'][env]['on'] (boolean)
174
+ feature_flag_variation_index_response: response (integer)
175
+ feature_flag_variation_value_response: response['variations'][feature_flag_variation_index_response]['value'] (object)
176
+ feature_flag_variation_name_response: response['variations'][feature_flag_variation_index_response]['name'] (string)
177
+ ```
178
+
179
+ ```ruby
180
+ def ld_rules_clauses_index(env, flag, clause_name)
181
+ # code ...
182
+ end
183
+ ```
184
+
185
+ ```ruby
186
+ def ld_get_values_from_clauses(env, flag, clause_name)
187
+ # code ...
188
+ end
189
+ ```
190
+
191
+ ```ruby
192
+ def ld_add_values_to_clause(env, flag, clause_name, clause_value)
193
+ # code ...
194
+ end
195
+ ```
196
+
197
+ ```ruby
198
+ def ld__remove_values_from_clause(env, flag, clause_name, clause_value)
199
+ # code ...
200
+ end
201
+ ```
202
+
203
+ ```ruby
204
+ def ld_delete_flag(flag)
205
+ # code ...
206
+ end
207
+ ```
20
208
 
21
209
  ## Development
22
210
 
@@ -21,4 +21,4 @@ REQUEST_CLASSES = {
21
21
  'code' => 204,
22
22
  'message' => 'No Content'
23
23
  }
24
- }.freeze
24
+ }.freeze
@@ -59,18 +59,18 @@ class LaunchdarklyApiHelperClass
59
59
  ld_request(:post, request_url, request_body)
60
60
  end
61
61
 
62
- def toggle_flag_for_specific_environment(env, flag, flag_value)
62
+ def toggle_specific_environment(env, flag, flag_value)
63
63
  request_url = "#{LAUNCH_DARKLY_FLAGS}/#{flag}"
64
64
  request_body = { 'op' => 'replace', 'path' => "/environments/#{env}/on", 'value' => flag_value }
65
65
  response_body = ld_request(:patch, request_url, [request_body])
66
66
  response_body['environments'][env]['on']
67
67
  end
68
68
 
69
- def feature_flag_variation_index(fetch_flag_toggle_status_response, fetch_flag_details_response)
70
- variations = fetch_flag_details_response['variations']
69
+ def feature_flag_variation_index(status_response, details_response)
70
+ variations = details_response['variations']
71
71
  value_at_index = -1
72
72
  variations.length.times do |index|
73
- next unless variations[index]['value'].eql? fetch_flag_toggle_status_response
73
+ next unless variations[index]['value'].eql? status_response
74
74
 
75
75
  value_at_index = index
76
76
  break
@@ -78,60 +78,81 @@ class LaunchdarklyApiHelperClass
78
78
  value_at_index
79
79
  end
80
80
 
81
- def feature_flag_variation_value(fetch_flag_details_response, feature_flag_variation_index_response)
82
- fetch_flag_details_response['variations'][feature_flag_variation_index_response]['value']
81
+ def feature_flag_variation_value(details_response, index_response)
82
+ details_response['variations'][index_response]['value']
83
83
  end
84
84
 
85
- def feature_flag_variation_name(fetch_flag_details_response, feature_flag_variation_index_response)
86
- fetch_flag_details_response['variations'][feature_flag_variation_index_response]['name']
85
+ def feature_flag_variation_name(details_response, index_response)
86
+ details_response['variations'][index_response]['name']
87
87
  end
88
88
 
89
- def toggle_variation_served_status(env, flag)
90
- fetch_flag_details_response = fetch_flag_details(env, flag)
91
- fetch_flag_toggle_status_response = fetch_flag_toggle_status(env, flag)
92
- feature_flag_variation_index_response = feature_flag_variation_index(fetch_flag_toggle_status_response, fetch_flag_details_response) # ['environments'][env]['fallthrough']['variation']
93
- feature_flag_variation_value_response = feature_flag_variation_value(fetch_flag_details_response, feature_flag_variation_index_response) # ['variations'][feature_flag_variation_index_response]['value']
94
- feature_flag_variation_name_response = feature_flag_variation_name(fetch_flag_details_response, feature_flag_variation_index_response)
95
- [fetch_flag_toggle_status_response, feature_flag_variation_index_response, feature_flag_variation_value_response, feature_flag_variation_name_response]
89
+ def ld_toggle_variation_served(env, flag)
90
+ details_response = fetch_flag_details(env, flag)
91
+ toggle_status_response = fetch_flag_toggle_status(env, flag)
92
+ variation_index_response = feature_flag_variation_index(toggle_status_response, details_response) # ['environments'][env]['fallthrough']['variation']
93
+ variation_value_response = feature_flag_variation_value(details_response, variation_index_response) # ['variations'][variation_index_response]['value']
94
+ variation_name_response = feature_flag_variation_name(details_response, variation_index_response)
95
+ [toggle_status_response, variation_index_response, variation_value_response, variation_name_response]
96
96
  end
97
97
 
98
- def search_value_in_hash(feature_flag_hash, attribute)
98
+ def search_rule_index_clause_index(clause_name)
99
+ rule_at_index = -1
100
+ clause_at_index = -1
101
+ @feature_flag_rules_list.length.times do |rule_index|
102
+ @feature_flag_clauses_list = @feature_flag_rules_list[rule_index]['clauses']
103
+ @feature_flag_clauses_list.length.times do |clause_index|
104
+ next unless @feature_flag_clauses_list[clause_index]['attribute'].eql? clause_name
105
+
106
+ rule_at_index = rule_index
107
+ clause_at_index = clause_index
108
+ break
109
+ end
110
+ end
111
+ [rule_at_index, clause_at_index]
112
+ end
113
+
114
+ def search_value_index(rule_at_index, clause_at_index, clause_value)
99
115
  value_at_index = -1
100
- feature_flag_hash.length.times do |index|
101
- next unless feature_flag_hash[index].to_s.include? attribute.to_s
116
+ @feature_flag_values_list = @feature_flag_rules_list[rule_at_index]['clauses'][clause_at_index]['values']
117
+ @feature_flag_values_list.length.times do |value_index|
118
+ next unless @feature_flag_values_list[value_index].eql? clause_value
102
119
 
103
- value_at_index = index
120
+ value_at_index = value_index
104
121
  break
105
122
  end
106
123
  value_at_index
107
124
  end
108
125
 
109
- def feature_flag_rules_clauses_index(flag, attribute, env = ENV['PROFILE'])
110
- @feature_flag_response = fetch_flag(flag, env)
111
- feature_flag_env = @feature_flag_response['environments'][env]
112
- @feature_flag_env_rules = feature_flag_env['rules']
113
- rule_index = search_value_in_hash(@feature_flag_env_rules, attribute)
114
- @feature_flag_env_rules_clauses = @feature_flag_env_rules[rule_index]['clauses']
115
- clause_index = search_value_in_hash(@feature_flag_env_rules_clauses, attribute)
116
- [rule_index, clause_index]
126
+ def rules_clauses_index(env, flag, clause_name)
127
+ feature_flag_response = fetch_flag_details(env, flag)
128
+ @feature_flag_rules_list = feature_flag_response['environments'][env]['rules']
129
+ search_rule_index_clause_index(clause_name)
117
130
  end
118
131
 
119
- def feature_flag_add_values_to_rules(flag, attribute, value, env = ENV['PROFILE'])
120
- @flag = flag
121
- @attribute = attribute
122
- @value = value
123
- @rule_index, @clause_index = feature_flag_rules_clauses_index(flag, attribute)
132
+ def get_values_from_clauses(env, flag, clause_name)
133
+ rule_at_index, clause_at_index = feature_flag_rules_clauses_index(env, flag, clause_name)
134
+ @feature_flag_rules_list[rule_at_index]['clauses'][clause_at_index]['values']
135
+ end
136
+
137
+ def add_values_to_clause(env, flag, clause_name, clause_value)
138
+ rule_at_index, clause_at_index = feature_flag_rules_clauses_index(env, flag, clause_name)
124
139
  request_url = "#{LAUNCH_DARKLY_FLAGS}/#{flag}"
125
- request_body = { 'op' => 'add', 'path' => "/environments/#{env}/rules/#{@rule_index}/clauses/#{@clause_index}/values/0", 'value' => value }
140
+ request_body = { 'op' => 'add', 'path' => "/environments/#{env}/rules/#{rule_at_index}/clauses/#{clause_at_index}/values/0", 'value' => clause_value }
126
141
  ld_request(:patch, request_url, [request_body])
127
142
  end
128
143
 
129
- def feature_flag_remove_values_to_rules(flag = @flag, attribute = @attribute, value = @value, env = ENV['PROFILE'])
130
- @rule_index, @clause_index = feature_flag_rules_clauses_index(flag, attribute, env = ENV['PROFILE']) unless flag || attribute
131
- feature_flag_env_rules_clauses_values = @feature_flag_env_rules_clauses[@clause_index]['values']
132
- value_index = search_value_in_hash(feature_flag_env_rules_clauses_values, value)
144
+ def remove_values_from_clause(env, flag, clause_name, clause_value)
145
+ rule_at_index, clause_at_index = feature_flag_rules_clauses_index(env, flag, clause_name)
146
+ value_at_index = search_value_index(rule_at_index, clause_at_index, clause_value)
147
+ puts "value_index: #{value_at_index}"
133
148
  request_url = "#{LAUNCH_DARKLY_FLAGS}/#{flag}"
134
- request_body = { 'op': 'test', 'path': "/environments/#{env}/rules/#{@rule_index}/clauses/#{@clause_index}/values/#{value_index}", 'value': value }, { 'op' => 'remove', 'path' => "/environments/#{env}/rules/#{@rule_index}/clauses/#{@clause_index}/values/#{value_index}" }
149
+ request_body = { 'op' => 'test', 'path' => "/environments/#{env}/rules/#{rule_at_index}/clauses/#{clause_at_index}/values/#{value_at_index}", 'value' => clause_value },
150
+ { 'op' => 'remove', 'path' => "/environments/#{env}/rules/#{rule_at_index}/clauses/#{clause_at_index}/values/#{value_at_index}" }
135
151
  ld_request(:patch, request_url, request_body)
136
152
  end
153
+
154
+ def delete_flag(flag)
155
+ request_url = "#{LAUNCH_DARKLY_FLAGS}/#{flag}"
156
+ ld_request(:delete, request_url)
157
+ end
137
158
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module LaunchdarklyApiHelper
4
- VERSION = '0.2.0'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -135,8 +135,8 @@ module LaunchdarklyApiHelper
135
135
  # == Here, 'developer_flag_for_regression' is the flag key and default is our Project name - Browserstack
136
136
  # == You can update any parameter of feature flag using this method
137
137
 
138
- def ld_toggle_flag_for_specific_environment(env, flag, flag_value = true)
139
- @launchdarkly_helper.toggle_flag_for_specific_environment(env, flag, flag_value)
138
+ def ld_toggle_specific_environment(env, flag, flag_value = true)
139
+ @launchdarkly_helper.toggle_specific_environment(env, flag, flag_value)
140
140
  end
141
141
 
142
142
  # == Get status of feature flag
@@ -144,12 +144,27 @@ module LaunchdarklyApiHelper
144
144
  #
145
145
  # [fetch_flag_toggle_status_response, feature_flag_variation_index_response, feature_flag_variation_value_response, feature_flag_variation_name_response]
146
146
 
147
- def ld_toggle_variation_served_status(env, flag)
148
- @launchdarkly_helper.toggle_variation_served_status(env, flag)
147
+ def ld_toggle_variation_served(env, flag)
148
+ @launchdarkly_helper.ld_toggle_variation_served(env, flag)
149
149
  end
150
150
 
151
- def delete_flag(flag)
152
- request_url = "#{LAUNCH_DARKLY_FLAGS}/#{flag}"
153
- ld_request(:delete, request_url)
151
+ def ld_rules_clauses_index(env, flag, clause_name)
152
+ @launchdarkly_helper.rules_clauses_index(env, flag, clause_name)
153
+ end
154
+
155
+ def ld_get_values_from_clauses(env, flag, clause_name)
156
+ @launchdarkly_helper.get_values_from_clauses(env, flag, clause_name)
157
+ end
158
+
159
+ def ld_add_values_to_clause(env, flag, clause_name, clause_value)
160
+ @launchdarkly_helper.add_values_to_clause(env, flag, clause_name, clause_value)
161
+ end
162
+
163
+ def ld__remove_values_from_clause(env, flag, clause_name, clause_value)
164
+ @launchdarkly_helper.remove_values_from_clause(env, flag, clause_name, clause_value)
165
+ end
166
+
167
+ def ld_delete_flag(flag)
168
+ @launchdarkly_helper.delete_flag(flag)
154
169
  end
155
170
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: launchdarkly_api_helper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - amit-singh-bisht
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-11-18 00:00:00.000000000 Z
11
+ date: 2022-11-19 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Write a longer description or delete this line.
14
14
  email: