ey-core 3.4.0 → 3.6.1

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.
Files changed (119) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +1 -0
  4. data/CHANGELOG.md +27 -5
  5. data/Gemfile +0 -1
  6. data/README.md +65 -8
  7. data/Rakefile +4 -1
  8. data/ey-core.gemspec +9 -5
  9. data/features/accounts.feature +13 -0
  10. data/features/applications.feature +29 -0
  11. data/features/current_user.feature +14 -0
  12. data/features/docker_registry_credentials.feature +21 -0
  13. data/features/environment_variables.feature +54 -0
  14. data/features/environments.feature +30 -0
  15. data/features/init.feature +6 -0
  16. data/features/login.feature +6 -0
  17. data/features/scp.feature +6 -0
  18. data/features/step_definitions/accounts_steps.rb +37 -0
  19. data/features/step_definitions/applications_steps.rb +39 -0
  20. data/features/step_definitions/current_user_steps.rb +11 -0
  21. data/features/step_definitions/deprecated_command_steps.rb +3 -0
  22. data/features/step_definitions/docker_registry_credentials_steps.rb +3 -0
  23. data/features/step_definitions/environment_variables_steps.rb +51 -0
  24. data/features/step_definitions/environments_steps.rb +52 -0
  25. data/features/step_definitions/version_steps.rb +3 -0
  26. data/features/support/account_helpers.rb +89 -0
  27. data/features/support/app_helpers.rb +19 -0
  28. data/features/support/aruba.rb +1 -0
  29. data/features/support/boilerplate.rb +1 -0
  30. data/features/support/client_helpers.rb +36 -0
  31. data/features/support/config_file_helpers.rb +42 -0
  32. data/features/support/core.rb +19 -0
  33. data/features/support/deployment_helpers.rb +19 -0
  34. data/features/support/env.rb +40 -0
  35. data/features/support/environment_helpers.rb +23 -0
  36. data/features/support/environment_variable_helpers.rb +20 -0
  37. data/features/support/fake_kernel.rb +23 -0
  38. data/features/support/io.rb +5 -0
  39. data/features/support/mock_api.rb +20 -0
  40. data/features/support/output_helpers.rb +7 -0
  41. data/features/support/resource_helpers.rb +201 -0
  42. data/features/support/server_helpers.rb +27 -0
  43. data/features/version.feature +8 -0
  44. data/features/whoami.feature +14 -0
  45. data/lib/ey-core/cli/deploy.rb +4 -4
  46. data/lib/ey-core/cli/docker_registry_login.rb +29 -0
  47. data/lib/ey-core/cli/environment_variables.rb +71 -0
  48. data/lib/ey-core/cli/helpers/core.rb +29 -0
  49. data/lib/ey-core/cli/main.rb +5 -4
  50. data/lib/ey-core/cli/servers.rb +35 -17
  51. data/lib/ey-core/cli/ssh.rb +1 -1
  52. data/lib/ey-core/client.rb +35 -0
  53. data/lib/ey-core/client/mock.rb +5 -0
  54. data/lib/ey-core/collections/auto_scaling_alarms.rb +8 -0
  55. data/lib/ey-core/collections/auto_scaling_groups.rb +8 -0
  56. data/lib/ey-core/collections/auto_scaling_policies.rb +33 -0
  57. data/lib/ey-core/collections/container_clusters.rb +9 -0
  58. data/lib/ey-core/collections/container_service_deployments.rb +17 -0
  59. data/lib/ey-core/collections/environment_variables.rb +8 -0
  60. data/lib/ey-core/collections/servers.rb +4 -0
  61. data/lib/ey-core/models/account.rb +10 -0
  62. data/lib/ey-core/models/address.rb +2 -0
  63. data/lib/ey-core/models/application.rb +1 -0
  64. data/lib/ey-core/models/auto_scaling_alarm.rb +54 -0
  65. data/lib/ey-core/models/auto_scaling_group.rb +75 -0
  66. data/lib/ey-core/models/base_auto_scaling_policy.rb +61 -0
  67. data/lib/ey-core/models/container_service_deployment.rb +17 -0
  68. data/lib/ey-core/models/environment.rb +60 -47
  69. data/lib/ey-core/models/environment_variable.rb +29 -0
  70. data/lib/ey-core/models/request.rb +6 -0
  71. data/lib/ey-core/models/server.rb +2 -0
  72. data/lib/ey-core/models/simple_auto_scaling_policy.rb +24 -0
  73. data/lib/ey-core/models/step_auto_scaling_policy.rb +24 -0
  74. data/lib/ey-core/models/target_auto_scaling_policy.rb +24 -0
  75. data/lib/ey-core/requests/boot_environment.rb +1 -1
  76. data/lib/ey-core/requests/create_account.rb +5 -0
  77. data/lib/ey-core/requests/create_address.rb +1 -0
  78. data/lib/ey-core/requests/create_application.rb +8 -7
  79. data/lib/ey-core/requests/create_auto_scaling_alarm.rb +69 -0
  80. data/lib/ey-core/requests/create_auto_scaling_group.rb +62 -0
  81. data/lib/ey-core/requests/create_auto_scaling_policy.rb +68 -0
  82. data/lib/ey-core/requests/create_environment.rb +2 -0
  83. data/lib/ey-core/requests/create_environment_variable.rb +39 -0
  84. data/lib/ey-core/requests/create_user.rb +8 -6
  85. data/lib/ey-core/requests/destroy_auto_scaling_alarm.rb +49 -0
  86. data/lib/ey-core/requests/destroy_auto_scaling_group.rb +44 -0
  87. data/lib/ey-core/requests/destroy_auto_scaling_policy.rb +49 -0
  88. data/lib/ey-core/requests/discover_container_service_deployments.rb +71 -0
  89. data/lib/ey-core/requests/discover_server.rb +60 -0
  90. data/lib/ey-core/requests/get_applications.rb +1 -1
  91. data/lib/ey-core/requests/get_auto_scaling_alarm.rb +27 -0
  92. data/lib/ey-core/requests/get_auto_scaling_alarms.rb +34 -0
  93. data/lib/ey-core/requests/get_auto_scaling_group.rb +21 -0
  94. data/lib/ey-core/requests/get_auto_scaling_groups.rb +29 -0
  95. data/lib/ey-core/requests/get_auto_scaling_policies.rb +46 -0
  96. data/lib/ey-core/requests/get_auto_scaling_policy.rb +27 -0
  97. data/lib/ey-core/requests/get_deployments.rb +1 -1
  98. data/lib/ey-core/requests/get_environment_variable.rb +19 -0
  99. data/lib/ey-core/requests/get_environment_variables.rb +29 -0
  100. data/lib/ey-core/requests/get_environments.rb +1 -1
  101. data/lib/ey-core/requests/get_ssl_certificate.rb +1 -1
  102. data/lib/ey-core/requests/retrieve_docker_registry_credentials.rb +24 -0
  103. data/lib/ey-core/requests/update_auto_scaling_alarm.rb +45 -0
  104. data/lib/ey-core/requests/update_auto_scaling_group.rb +45 -0
  105. data/lib/ey-core/requests/update_auto_scaling_policy.rb +46 -0
  106. data/lib/ey-core/requests/update_environment_variable.rb +25 -0
  107. data/lib/ey-core/test_helpers.rb +2 -0
  108. data/lib/ey-core/test_helpers/auto_scaling_helpers.rb +35 -0
  109. data/lib/ey-core/version.rb +1 -1
  110. data/spec/addresses_spec.rb +2 -1
  111. data/spec/auto_scaling_alarms_spec.rb +40 -0
  112. data/spec/auto_scaling_groups_spec.rb +28 -0
  113. data/spec/auto_scaling_policies_spec.rb +94 -0
  114. data/spec/docker_registry_credentials_spec.rb +16 -0
  115. data/spec/environments_spec.rb +18 -0
  116. data/spec/servers_spec.rb +8 -0
  117. data/spec/spec_helper.rb +7 -0
  118. data/spec/support/core.rb +0 -2
  119. metadata +192 -18
@@ -0,0 +1,23 @@
1
+ module EnvironmentHelpers
2
+ def environment_named(name)
3
+ client.environments.first(name: name)
4
+ end
5
+
6
+ def known_environments
7
+ begin
8
+ recall_fact(:known_environments)
9
+ rescue
10
+ memorize_fact(:known_environments, [])
11
+ end
12
+ end
13
+
14
+ def first_environment
15
+ known_environments.first.reload
16
+ end
17
+
18
+ def last_environment
19
+ known_environments.last.reload
20
+ end
21
+ end
22
+
23
+ World(EnvironmentHelpers)
@@ -0,0 +1,20 @@
1
+ module EnvironmentVariableHelpers
2
+ ENVIRONMENT_VARIABLE_DISPLAY_FIELDS = %i[id name value environment_name application_name]
3
+
4
+ def known_environment_variables
5
+ begin
6
+ recall_fact(:environment_variables)
7
+ rescue
8
+ memorize_fact(:environment_variables, [])
9
+ end
10
+ end
11
+
12
+ def match_environment_variable_regexp(environment_variable)
13
+ regexp_parts = ENVIRONMENT_VARIABLE_DISPLAY_FIELDS.map do |field|
14
+ Regexp.escape(environment_variable.send(field).to_s)
15
+ end
16
+ Regexp.new(regexp_parts.join("(\s+)\\|(\s+)"))
17
+ end
18
+ end
19
+
20
+ World(EnvironmentVariableHelpers)
@@ -0,0 +1,23 @@
1
+ require 'aruba/processes/in_process'
2
+
3
+ module Aruba
4
+ module Processes
5
+ class InProcess < BasicProcess
6
+ attr_reader :kernel
7
+
8
+ class FakeKernel
9
+ def system(*args)
10
+ system_commands.push(args.join(' '))
11
+ end
12
+
13
+ def system_commands
14
+ @system_commands ||= []
15
+ end
16
+
17
+ def abort(msg)
18
+ exit(false)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ After do
2
+ $stdout = STDOUT
3
+ $stdin = STDIN
4
+ $stderr = STDERR
5
+ end
@@ -0,0 +1,20 @@
1
+ require 'cucumber/rspec/doubles'
2
+
3
+ # Set up the mocks. Ookla would approve.
4
+ Ey::Core::Client.mock!
5
+ Ey::Core::Client::Mock.timeout = 0.1
6
+ Ey::Core::Client::Mock.poll_interval = 0
7
+ Ey::Core::Client::Real.timeout = 3
8
+ Ey::Core::Client::Real.poll_interval = 0
9
+
10
+ Before do
11
+ # Reset the mocked API before every scenario
12
+ Ey::Core::Client::Mock.reset!
13
+
14
+ # Stub out `#core_client` on all subcommands to ensure that they're using
15
+ # the mocked client. Otherwise, everything turns to calamity, because the
16
+ # mocked API is silly.
17
+ allow_any_instance_of(Ey::Core::Cli::Subcommand).
18
+ to receive(:core_client).
19
+ and_return(client)
20
+ end
@@ -0,0 +1,7 @@
1
+ module OutputHelpers
2
+ def output_text
3
+ last_command_started.output
4
+ end
5
+ end
6
+
7
+ World(OutputHelpers)
@@ -0,0 +1,201 @@
1
+ module ResourceHelpers
2
+ def load_blueprint(options={})
3
+ application = create_application(account: account)
4
+ database_service = create_database_service(provider: account.providers.first)
5
+ environment = create_environment(account: account, application: application, database_service: database_service, environment: {name: "environment#{SecureRandom.hex(4)}"})
6
+
7
+ [database_service, environment]
8
+ end
9
+
10
+ def create_application(options={})
11
+ account = options.delete(:account) || create_account(options)
12
+ options = Cistern::Hash.stringify_keys(options)
13
+
14
+ options["name"] ||= "application#{SecureRandom.hex(4)}"
15
+ options["repository"] ||= "git://github.com/engineyard/todo.git"
16
+ options["type"] ||= "rails4"
17
+
18
+ account.applications.create!(options)
19
+ end
20
+
21
+ def create_server(client, options={})
22
+ options = Cistern::Hash.stringify_keys(options)
23
+
24
+ request = environment.servers.create(
25
+ "flavor" => "m3.medium",
26
+ "role" => "util",
27
+ )
28
+
29
+ request.resource!
30
+ end
31
+
32
+ def create_cost(client, options={})
33
+ account = options[:account] || create_account(client: client)
34
+ level = options[:level] || "summarized"
35
+ finality = options[:finality] || "estimated"
36
+ related_resource_type = options[:related_resource_type] || "account"
37
+ category = options[:category] || "non-server"
38
+ description = options[:description] || "AWS Other Services"
39
+ value = options[:value] || "1763"
40
+ environment = options[:environment] || nil
41
+
42
+ client.data[:costs] << {
43
+ billing_month: "2015-07",
44
+ data_type: "cost",
45
+ level: level,
46
+ finality: finality,
47
+ related_resource_type: related_resource_type,
48
+ category: category,
49
+ units: "USD cents",
50
+ description: description,
51
+ value: value,
52
+ account: client.url_for("accounts/#{account.identity}"),
53
+ environment: environment
54
+ }
55
+ end
56
+
57
+ def create_account_referral(client, options={})
58
+ referred = options.delete(:referred) || create_account(client: client)
59
+ referrer = options.delete(:referrer) || create_account(client: client)
60
+
61
+ account_referral_id = SecureRandom.uuid
62
+ referral = client.data[:account_referrals][account_referral_id] = {
63
+ "id" => account_referral_id,
64
+ "referrer" => client.url_for("accounts/#{referrer.identity}"),
65
+ "referred" => client.url_for("accounts/#{referred.identity}"),
66
+ }
67
+
68
+ client.account_referrals.new(referral)
69
+ end
70
+
71
+ def create_firewall(client, options={})
72
+ provider = options.fetch(:provider) { create_provider(client: client) }
73
+
74
+ firewall_params = options[:firewall] || {}
75
+ name = firewall_params.delete(:name) || SecureRandom.hex(6)
76
+ location = firewall_params.delete(:location) || "us-west-2"
77
+
78
+ client.firewalls.create!(
79
+ :name => name,
80
+ :location => location,
81
+ :provider => provider,
82
+ ).resource!
83
+ end
84
+
85
+ def create_database_service(options={})
86
+ provider = options[:provider] || create_provider(options.merge(client: client))
87
+
88
+ database_service_params = Hashie::Mash.new(
89
+ :name => Faker::Name.first_name,
90
+ :provider => provider,
91
+ ).merge(options.fetch(:database_service, {}))
92
+
93
+ database_server_params = Hashie::Mash.new(
94
+ :location => "us-west-2c",
95
+ :flavor => "db.m3.large",
96
+ :engine => "postgres",
97
+ :version => "9.3.5",
98
+ ).merge(options.fetch(:database_server, {}))
99
+
100
+ client.database_services.create!(database_service_params.merge(database_server: database_server_params)).resource!
101
+ end
102
+
103
+ def create_environment(options={})
104
+ account = options[:account] || create_account(options)
105
+
106
+ unless account.providers.first || options[:provider]
107
+ create_provider(account: account)
108
+ end
109
+
110
+ environment = options[:environment] || {}
111
+ application = options[:application] || create_application(account: account)
112
+ database_service = options[:database_service]
113
+ configuration = Cistern::Hash.stringify_keys(options[:configuration] || {})
114
+ configuration["type"] = "production-cluster" if configuration["type"] == "production"
115
+ configuration["type"] ||= "solo"
116
+ environment[:name] ||= options.fetch(:name, SecureRandom.hex(3))
117
+ environment[:region] ||= "us-west-2"
118
+
119
+ environment.merge!(application_id: application.id, account: account)
120
+ environment.merge!(database_service: database_service) if database_service
121
+ environment = client.environments.create!(environment)
122
+
123
+ unless options[:boot] == false
124
+ request = environment.boot(configuration: configuration, application_id: application.id)
125
+ request.ready!
126
+ end
127
+ environment
128
+ end
129
+
130
+ def create_environment_variable(options={})
131
+ application = options[:application] || create_application
132
+ environment = options[:environment] || create_environment
133
+
134
+ environment_variable = options[:environment_variable] || {}
135
+ environment_variable.merge!(application_id: application.id, environment: environment.id)
136
+ environment_variable[:name] ||= SecureRandom.hex(8)
137
+ environment_variable[:value] ||= SecureRandom.hex(32)
138
+
139
+ client.environment_variables.create!(environment_variable)
140
+ end
141
+
142
+ def create_provider_location(client, attributes={})
143
+ attributes = Cistern::Hash.stringify_keys(attributes)
144
+
145
+ if provider = attributes.delete("provider")
146
+ attributes["provider"] = client.url_for("/providers/#{provider.id}")
147
+ end
148
+
149
+ attributes["id"] ||= client.uuid
150
+ client.data[:provider_locations][attributes["id"]] = attributes
151
+
152
+ client.provider_locations.new(attributes)
153
+ end
154
+
155
+ def create_server_event(client, attributes={})
156
+ attributes = Cistern::Hash.stringify_keys(attributes)
157
+
158
+ attributes.fetch("type")
159
+
160
+ if server = attributes.delete("server")
161
+ attributes["server"] = client.url_for("/servers/#{server.id}")
162
+ end
163
+
164
+ event_id = attributes["id"] ||= SecureRandom.uuid
165
+
166
+ client.server_events.new(
167
+ client.data[:server_events][event_id] = attributes
168
+ )
169
+ end
170
+
171
+ def create_logical_database(options={})
172
+ database_service = options.fetch(:database_service) { create_database_service(options) }
173
+
174
+ database_service.databases.create!(
175
+ :name => SecureRandom.hex(6),
176
+ :username => "ey#{SecureRandom.hex(6)}",
177
+ :password => SecureRandom.hex(8),
178
+ ).resource!
179
+ end
180
+
181
+ def create_untracked_server(options={})
182
+ provider = options.fetch(:provider) { create_provider(options) }
183
+
184
+ untracked_server = options[:untracked_server] || {}
185
+
186
+ provisioner_id = untracked_server[:provisioner_id] || SecureRandom.uuid
187
+ location = untracked_server[:location] || "us-west-2b"
188
+ provisioned_id = untracked_server[:provisioned_id] || "i-#{SecureRandom.hex(4)}"
189
+ state = untracked_server[:state] || "found"
190
+
191
+ client.untracked_servers.create(
192
+ :location => location,
193
+ :provider => provider,
194
+ :provisioned_id => provisioned_id,
195
+ :provisioner_id => provisioner_id,
196
+ :state => state,
197
+ )
198
+ end
199
+ end
200
+
201
+ World(ResourceHelpers)
@@ -0,0 +1,27 @@
1
+ module ServerHelpers
2
+ def known_servers
3
+ begin
4
+ recall_fact(:known_servers)
5
+ rescue
6
+ memorize_fact(:known_servers, [])
7
+ end
8
+ end
9
+
10
+ def seen_servers
11
+ begin
12
+ recall_fact(:seen_servers)
13
+ rescue
14
+ memorize_fact(:seen_servers, [])
15
+ end
16
+ end
17
+
18
+ def first_server
19
+ known_servers.first
20
+ end
21
+
22
+ def last_server
23
+ known_servers.last
24
+ end
25
+ end
26
+
27
+ World(ServerHelpers)
@@ -0,0 +1,8 @@
1
+ Feature: Version
2
+ In order to determine if I'm working with the most recent goodness
3
+ As a User
4
+ I want to know what version of ey-core I'm using
5
+
6
+ Scenario: Displaying the version
7
+ When I run `ey-core version`
8
+ Then I see the current ey-core version
@@ -0,0 +1,14 @@
1
+ Feature: Whoami
2
+ In order to ensure that I'm logged into the right account
3
+ As a User
4
+ I want to be able to see my user information
5
+
6
+ Background:
7
+ Given I'm an Engine Yard user
8
+ And ey-core is configured with my cloud token
9
+
10
+ Scenario: Getting the current user information
11
+ When I run `ey-core whoami`
12
+ Then I should see my user ID
13
+ And I should see my email address
14
+ And I should see my name
@@ -91,14 +91,14 @@ EOF
91
91
  raise "--ref is required (HEAD is the typical choice)"
92
92
  end
93
93
  end
94
- if (switch_active?(:migrate) || switch_active?(:no_migrate))
95
- deploy_options.merge!(migrate_command: option(:migrate)) if switch_active?(:migrate)
96
- deploy_options.merge!(migrate_command: '') if switch_active?(:no_migrate)
94
+ if (option(:migrate) || switch_active?(:no_migrate))
95
+ deploy_options.merge!(migrate_command: option(:migrate)) if option(:migrate)
96
+ deploy_options.merge!(migrate_command: nil) if switch_active?(:no_migrate)
97
97
  else
98
98
  puts "missing migrate option (--migrate or --no-migrate), checking latest deploy...".yellow
99
99
  latest_deploy ||= environment.latest_deploy(app)
100
100
  if latest_deploy
101
- deploy_options.merge!(migrate_command: (latest_deploy.migrate && latest_deploy.migrate_command) || '')
101
+ deploy_options.merge!(migrate_command: (latest_deploy.migrate && latest_deploy.migrate_command) || nil)
102
102
  else
103
103
  raise "either --migrate or --no-migrate needs to be specified"
104
104
  end
@@ -0,0 +1,29 @@
1
+ require 'ey-core/cli/subcommand'
2
+
3
+ module Ey
4
+ module Core
5
+ module Cli
6
+ class DockerRegistryLogin < Subcommand
7
+ title "get-docker-registry-login"
8
+ summary "Prints the docker login command to authorize the Docker Engine with the AWS ECR registry"
9
+
10
+ option :account,
11
+ short: 'c',
12
+ long: 'account',
13
+ description: 'Name or ID of the account that the environment resides in.',
14
+ argument: 'Account name or id'
15
+
16
+ option :location,
17
+ short: 'l',
18
+ long: 'location',
19
+ description: 'ECR availability regions',
20
+ argument: 'Location name'
21
+
22
+ def handle
23
+ credentials = core_account.retrieve_docker_registry_credentials(option(:location))
24
+ stdout.puts "docker login -u #{credentials.username} -p #{credentials.password} #{credentials.registry_endpoint}"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,71 @@
1
+ require 'ey-core/cli/subcommand'
2
+ require 'ey-core/cli/helpers/stream_printer'
3
+
4
+ module Ey
5
+ module Core
6
+ module Cli
7
+ class EnvironmentVariables < Subcommand
8
+ MASK = '****'.freeze
9
+ SYMBOLS_TO_DISPLAY = 4
10
+ MAX_LENGTH_TO_DISPLAY = 30
11
+
12
+ include Ey::Core::Cli::Helpers::StreamPrinter
13
+
14
+ title "environment_variables"
15
+ summary "Retrieve a list of Engine Yard environment variables for environments that you have access to."
16
+
17
+ option :environment,
18
+ short: 'e',
19
+ long: 'environment',
20
+ description: 'Filter by environmeent name or id',
21
+ argument: 'Environment'
22
+
23
+ option :application,
24
+ short: 'a',
25
+ long: 'application',
26
+ description: 'Filter by application name or id',
27
+ argument: 'Application'
28
+
29
+ switch :display_sensitive,
30
+ short: 's',
31
+ long: 'display_sensitive',
32
+ description: 'Determines whether values of sensitive variables should be printed',
33
+ argument: 'Display Sensitive'
34
+
35
+ def handle
36
+ environment_variables = if option(:application)
37
+ core_applications(option(:application)).flat_map(&:environment_variables)
38
+ elsif option(:environment)
39
+ core_environments(option(:environment)).flat_map(&:environment_variables)
40
+ else
41
+ core_environment_variables
42
+ end
43
+
44
+ stream_print("ID" => 10, "Name" => 30, "Value" => 50, "Environment" => 30, "Application" => 30) do |printer|
45
+ environment_variables.each_entry do |ev|
46
+ printer.print(ev.id, ev.name, print_variable_value(ev), ev.environment_name, ev.application_name)
47
+ end
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def print_variable_value(environment_variable)
54
+ if environment_variable.sensitive && !switch_active?(:display_sensitive)
55
+ hide_sensitive_data(environment_variable.value)
56
+ else
57
+ environment_variable.value
58
+ end
59
+ end
60
+
61
+ def hide_sensitive_data(value)
62
+ if value.length > SYMBOLS_TO_DISPLAY
63
+ MASK + value[-SYMBOLS_TO_DISPLAY, SYMBOLS_TO_DISPLAY]
64
+ else
65
+ MASK
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end