seira 0.5.1 → 0.5.2

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: 87fa02469006bc2145037e07818f61879777d8345c5a5270f2d8faad32640599
4
- data.tar.gz: 57b21d9c6f6507afe943fba5519ca0f118207c0d5844d544a529e6c26d3d4d00
3
+ metadata.gz: 7064ff568c67e81e0cdb84bc98fe1420b392ab69174ad39a2d96c81ae59615f5
4
+ data.tar.gz: 41024bad248f6e8631587d0fd7d6bb0c6db49fd9ce8da58bd85330f46d321345
5
5
  SHA512:
6
- metadata.gz: 04e53ae6f602a47299d4829ec25dde2adf76b201f888130c8f5fc686da4167ee32682090029dbb9b1cdde60438e51dd95d162455a4aec9bf002cad3f079bfc5b
7
- data.tar.gz: 7187058bc0a2d9406469bebf44b351346acd0164d7cd59b6895f08e5658a9f957fd168543ae0a98496206d3014f10cc7e20a9b82e55a25145ee72fedc80d80e3
6
+ metadata.gz: 85ce01cc44b6d88ab6890a93d2228e323cb277f797b1fecdd3ca763d5a00668092949dcdcd1f1fc79bd5f6412e04d40486884b62dd8b0556e015442713b1bb27
7
+ data.tar.gz: 599e8c0a21b0e6f1df8dac190a1c6d12be34fc9f2eceaf425ac4b8ec7b78c4163d4e5ad6be35daf6ae8c206f66cc2e12017617be69944d8f7c5812122992fcb6
@@ -0,0 +1,42 @@
1
+ module Seira
2
+ class Db
3
+ class AlterProxyuserRoles
4
+ include Seira::Commands
5
+
6
+ attr_reader :name, :root_password
7
+
8
+ def initialize(app:, action:, args:, context:)
9
+ if args.length != 2
10
+ puts 'Specify db name and root password as the positional arguments'
11
+ exit(1)
12
+ end
13
+
14
+ @name = args[0]
15
+ @root_password = args[1]
16
+ end
17
+
18
+ def run
19
+ # Connect to the instance and remove some of the default group memberships and permissions
20
+ # from proxyuser, leaving it with only what it needs to be able to do
21
+ expect_script = <<~BASH
22
+ set timeout 90
23
+ spawn gcloud sql connect #{name}
24
+ expect "Password for user postgres:"
25
+ send "#{root_password}\\r"
26
+ expect "postgres=>"
27
+ send "ALTER ROLE proxyuser NOCREATEDB NOCREATEROLE;\\r"
28
+ expect "postgres=>"
29
+ BASH
30
+ if system("expect <<EOF\n#{expect_script}EOF")
31
+ puts "Successfully removed unnecessary permissions from proxyuser"
32
+ else
33
+ puts "Failed to remove unnecessary permissions from proxyuser."
34
+ puts "You may need to whitelist the correct IP in the gcloud UI."
35
+ puts "You can get the correct IP from https://www.whatismyip.com/"
36
+ puts "Make sure to remove it from the whitelist after successfully running db alter-proxyuser-roles"
37
+ exit(1)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -40,6 +40,8 @@ module Seira
40
40
  set_secrets
41
41
  write_pgbouncer_yaml
42
42
 
43
+ alter_proxy_user_roles if replica_for.nil?
44
+
43
45
  puts "To use this database, deploy the pgbouncer config file that was created and use the ENV that was set."
44
46
  puts "To make this database the primary, promote it using the CLI and update the DATABASE_URL."
45
47
  end
@@ -79,6 +81,7 @@ module Seira
79
81
 
80
82
  # Basic configs
81
83
  create_command += " --database-version=#{version}"
84
+ create_command += " --network=default" # allow network to be configurable?
82
85
 
83
86
  # A read replica cannot have HA, inherits the cpu, mem and storage of its primary
84
87
  if replica_for.nil?
@@ -115,7 +118,7 @@ module Seira
115
118
  # Set the root user's password to something secure
116
119
  @root_password = SecureRandom.urlsafe_base64(32)
117
120
 
118
- if gcloud("sql users set-password postgres '' --instance=#{name} --password=#{root_password}", context: context, format: :boolean)
121
+ if gcloud("sql users set-password postgres --instance=#{name} --password=#{root_password}", context: context, format: :boolean)
119
122
  puts "Set root password to #{root_password}"
120
123
  else
121
124
  puts "Failed to set root password"
@@ -127,30 +130,16 @@ module Seira
127
130
  # Create proxyuser with secure password
128
131
  @proxyuser_password = SecureRandom.urlsafe_base64(32)
129
132
 
130
- if gcloud("sql users create proxyuser '' --instance=#{name} --password=#{proxyuser_password}", context: context, format: :boolean)
133
+ if gcloud("sql users create proxyuser --instance=#{name} --password=#{proxyuser_password}", context: context, format: :boolean)
131
134
  puts "Created proxyuser with password #{proxyuser_password}"
132
135
  else
133
136
  puts "Failed to create proxyuser"
134
137
  exit(1)
135
138
  end
139
+ end
136
140
 
137
- # Connect to the instance and remove some of the default group memberships and permissions
138
- # from proxyuser, leaving it with only what it needs to be able to do
139
- expect_script = <<~BASH
140
- set timeout 90
141
- spawn gcloud sql connect #{name}
142
- expect "Password for user postgres:"
143
- send "#{root_password}\\r"
144
- expect "postgres=>"
145
- send "ALTER ROLE proxyuser NOCREATEDB NOCREATEROLE;\\r"
146
- expect "postgres=>"
147
- BASH
148
- if system("expect <<EOF\n#{expect_script}EOF")
149
- puts "Successfully removed unnecessary permissions from proxyuser"
150
- else
151
- puts "Failed to remove unnecessary permissions from proxyuser"
152
- exit(1)
153
- end
141
+ def alter_proxy_user_roles
142
+ Seira::Db::AlterProxyuserRoles.new(app: app, action: action, args: [name, root_password], context: context).run
154
143
  end
155
144
 
156
145
  def set_secrets
@@ -186,10 +175,6 @@ module Seira
186
175
  "#{name}-pgbouncer-secrets"
187
176
  end
188
177
 
189
- def pgbouncer_configs_name
190
- "#{name}-pgbouncer-configs"
191
- end
192
-
193
178
  def pgbouncer_service_name
194
179
  "#{name}-pgbouncer-service"
195
180
  end
@@ -202,11 +187,21 @@ module Seira
202
187
  "#{app}_#{Helpers.rails_env(context: context)}"
203
188
  end
204
189
 
190
+ def ips
191
+ @_ips ||= begin
192
+ describe_command = "sql instances describe #{name}"
193
+ json = JSON.parse(gcloud(describe_command, context: context, format: :json))
194
+ private_ip = json['ipAddresses'].find { |address| address['type'] == 'PRIVATE' }['ipAddress']
195
+ public_ip = json['ipAddresses'].find { |address| address['type'] == 'PRIMARY' }['ipAddress']
196
+ { private: private_ip, public: public_ip }
197
+ end
198
+ end
199
+
205
200
  def write_pgbouncer_yaml
206
201
  # TODO: Clean this up by moving into a proper templated yaml file
207
202
  pgbouncer_yaml = <<-FOO
208
203
  ---
209
- apiVersion: extensions/v1beta1
204
+ apiVersion: apps/v1
210
205
  kind: Deployment
211
206
  metadata:
212
207
  name: #{name}-pgbouncer
@@ -217,6 +212,11 @@ metadata:
217
212
  database: #{name}
218
213
  spec:
219
214
  replicas: 2
215
+ selector:
216
+ matchLabels:
217
+ app: #{app}
218
+ tier: #{pgbouncer_tier}
219
+ database: #{name}
220
220
  strategy:
221
221
  type: RollingUpdate
222
222
  rollingUpdate:
@@ -236,8 +236,6 @@ spec:
236
236
  - containerPort: 6432
237
237
  protocol: TCP
238
238
  envFrom:
239
- - configMapRef:
240
- name: #{pgbouncer_configs_name}
241
239
  - secretRef:
242
240
  name: #{pgbouncer_secret_name}
243
241
  env:
@@ -246,7 +244,7 @@ spec:
246
244
  - name: "PGDATABASE"
247
245
  value: "#{@database_name || default_database_name}"
248
246
  - name: "DB_HOST"
249
- value: "127.0.0.1" # Exposed by cloudsql proxy
247
+ value: "#{ips[:private]}" # private IP for #{name}
250
248
  - name: "DB_PORT"
251
249
  value: "5432"
252
250
  - name: "LISTEN_PORT"
@@ -287,33 +285,10 @@ spec:
287
285
  requests:
288
286
  cpu: 100m
289
287
  memory: 300Mi
290
- - image: gcr.io/cloudsql-docker/gce-proxy:1.11 # Gcloud SQL Proxy
291
- name: cloudsql-proxy
292
- command:
293
- - /cloud_sql_proxy
294
- - --dir=/cloudsql
295
- - -instances=#{context[:project]}:#{context[:region]}:#{name}=tcp:5432
296
- - -credential_file=/secrets/cloudsql/credentials.json
297
- ports:
298
- - containerPort: 5432
299
- protocol: TCP
300
- volumeMounts:
301
- - name: cloudsql-credentials
302
- mountPath: /secrets/cloudsql
303
- readOnly: true
304
- - name: ssl-certs
305
- mountPath: /etc/ssl/certs
306
- - name: cloudsql
307
- mountPath: /cloudsql
308
- volumes:
309
- - name: cloudsql-credentials
310
- secret:
311
- secretName: cloudsql-credentials
312
- - name: cloudsql
313
- emptyDir:
314
- - name: ssl-certs
315
- hostPath:
316
- path: /etc/ssl/certs
288
+ lifecycle:
289
+ preStop:
290
+ exec:
291
+ command: ["/bin/sh", "-c", "killall -INT pgbouncer && sleep 20"]
317
292
  ---
318
293
  apiVersion: v1
319
294
  kind: Service
@@ -324,12 +299,11 @@ metadata:
324
299
  app: #{app}
325
300
  tier: #{pgbouncer_tier}
326
301
  spec:
327
- type: NodePort
302
+ type: ClusterIP
328
303
  ports:
329
- - protocol: TCP
330
- port: 6432
331
- targetPort: 6432
332
- nodePort: 0
304
+ - protocol: TCP
305
+ port: 6432
306
+ targetPort: 6432
333
307
  selector:
334
308
  app: #{app}
335
309
  tier: #{pgbouncer_tier}
data/lib/seira/db.rb CHANGED
@@ -1,13 +1,14 @@
1
1
  require 'securerandom'
2
2
  require 'English'
3
3
 
4
+ require_relative 'db/alter_proxyuser_roles'
4
5
  require_relative 'db/create'
5
6
 
6
7
  module Seira
7
8
  class Db
8
9
  include Seira::Commands
9
10
 
10
- VALID_ACTIONS = %w[help create delete list restart connect ps kill analyze create-readonly-user psql table-sizes index-sizes vacuum unused-indexes unused-indices user-connections info].freeze
11
+ VALID_ACTIONS = %w[help create delete list restart connect ps kill analyze create-readonly-user psql table-sizes index-sizes vacuum unused-indexes unused-indices user-connections info alter-proxyuser-roles].freeze
11
12
  SUMMARY = "Manage your Cloud SQL Postgres databases.".freeze
12
13
 
13
14
  attr_reader :app, :action, :args, :context
@@ -55,6 +56,8 @@ module Seira
55
56
  run_user_connections
56
57
  when 'info'
57
58
  run_info
59
+ when 'alter-proxyuser-roles'
60
+ run_alter_proxyuser_roles
58
61
  else
59
62
  fail "Unknown command encountered"
60
63
  end
@@ -78,22 +81,23 @@ module Seira
78
81
  puts SUMMARY
79
82
  puts "\n"
80
83
  puts <<~HELPTEXT
81
- analyze: Display database performance information
82
- connect: Open a psql command prompt via gcloud connect. You will be shown the password needed before the prompt opens.
83
- create: Create a new postgres instance in cloud sql. Supports creating replicas and other numerous flags.
84
- create-readonly-user: Create a database user named by --username=<name> with only SELECT access privileges
85
- delete: Delete a postgres instance from cloud sql. Use with caution, and remove all kubernetes configs first.
86
- index-sizes: List sizes of all indexes in the database
87
- info: Summarize all database instances for the app
88
- kill: Kill a query
89
- list: List all postgres instances.
90
- ps: List running queries
91
- psql: Open a psql prompt via kubectl exec into a pgbouncer pod.
92
- restart: Fully restart the database.
93
- table-sizes: List sizes of all tables in the database
94
- unused-indexes: Show indexes with zero or low usage
95
- user-connections: List number of connections per user
96
- vacuum: Run a VACUUM ANALYZE
84
+ analyze: Display database performance information
85
+ connect: Open a psql command prompt via gcloud connect. You will be shown the password needed before the prompt opens.
86
+ create: Create a new postgres instance in cloud sql. Supports creating replicas and other numerous flags.
87
+ create-readonly-user: Create a database user named by --username=<name> with only SELECT access privileges
88
+ delete: Delete a postgres instance from cloud sql. Use with caution, and remove all kubernetes configs first.
89
+ index-sizes: List sizes of all indexes in the database
90
+ info: Summarize all database instances for the app
91
+ kill: Kill a query
92
+ list: List all postgres instances.
93
+ ps: List running queries
94
+ psql: Open a psql prompt via kubectl exec into a pgbouncer pod.
95
+ restart: Fully restart the database.
96
+ table-sizes: List sizes of all tables in the database
97
+ unused-indexes: Show indexes with zero or low usage
98
+ user-connections: List number of connections per user
99
+ vacuum: Run a VACUUM ANALYZE
100
+ alter-proxyuser-roles: Update NOCREATEDB and NOCREATEROLE roles for proxyuser in cloud sql.
97
101
  HELPTEXT
98
102
  end
99
103
 
@@ -101,6 +105,10 @@ module Seira
101
105
  Seira::Db::Create.new(app: app, action: action, args: args, context: context).run(existing_instances)
102
106
  end
103
107
 
108
+ def run_alter_proxyuser_roles
109
+ Seira::Db::AlterProxyuserRoles.new(app: app, action: action, args: args, context: context).run
110
+ end
111
+
104
112
  def run_delete
105
113
  name = "#{app}-#{args[0]}"
106
114
  if gcloud("sql instances delete #{name}", context: context, format: :boolean)
data/lib/seira/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Seira
2
- VERSION = "0.5.1".freeze
2
+ VERSION = "0.5.2".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seira
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.1
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Ringwelski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-18 00:00:00.000000000 Z
11
+ date: 2018-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: highline
@@ -124,6 +124,7 @@ files:
124
124
  - lib/seira/commands/gcloud.rb
125
125
  - lib/seira/commands/kubectl.rb
126
126
  - lib/seira/db.rb
127
+ - lib/seira/db/alter_proxyuser_roles.rb
127
128
  - lib/seira/db/create.rb
128
129
  - lib/seira/jobs.rb
129
130
  - lib/seira/memcached.rb