google-cloud-gemserver 0.1.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 +7 -0
- data/.yardopts +7 -0
- data/CONTRIBUTING.md +49 -0
- data/LICENSE +202 -0
- data/README.md +179 -0
- data/bin/console +7 -0
- data/bin/google-cloud-gemserver +5 -0
- data/bin/setup +6 -0
- data/lib/google/cloud/gemserver.rb +33 -0
- data/lib/google/cloud/gemserver/authentication.rb +254 -0
- data/lib/google/cloud/gemserver/backend.rb +33 -0
- data/lib/google/cloud/gemserver/backend/gemstash_server.rb +60 -0
- data/lib/google/cloud/gemserver/backend/key.rb +152 -0
- data/lib/google/cloud/gemserver/backend/stats.rb +149 -0
- data/lib/google/cloud/gemserver/backend/storage_sync.rb +186 -0
- data/lib/google/cloud/gemserver/cli.rb +174 -0
- data/lib/google/cloud/gemserver/cli/cloud_sql.rb +196 -0
- data/lib/google/cloud/gemserver/cli/project.rb +143 -0
- data/lib/google/cloud/gemserver/cli/request.rb +130 -0
- data/lib/google/cloud/gemserver/cli/server.rb +337 -0
- data/lib/google/cloud/gemserver/configuration.rb +505 -0
- data/lib/google/cloud/gemserver/gcs.rb +171 -0
- data/lib/google/cloud/gemserver/version.rb +23 -0
- data/lib/patched/configuration.rb +29 -0
- data/lib/patched/dependencies.rb +33 -0
- data/lib/patched/env.rb +42 -0
- data/lib/patched/gem_pusher.rb +28 -0
- data/lib/patched/gem_yanker.rb +28 -0
- data/lib/patched/storage.rb +37 -0
- data/lib/patched/web.rb +64 -0
- metadata +271 -0
@@ -0,0 +1,196 @@
|
|
1
|
+
# Copyright 2017 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "google/cloud/gemserver"
|
16
|
+
require "securerandom"
|
17
|
+
require "google/apis/sqladmin_v1beta4"
|
18
|
+
require "googleauth"
|
19
|
+
require "yaml"
|
20
|
+
|
21
|
+
module Google
|
22
|
+
module Cloud
|
23
|
+
module Gemserver
|
24
|
+
class CLI
|
25
|
+
##
|
26
|
+
# # CloudSQL
|
27
|
+
#
|
28
|
+
# CloudSQL manages the creation of a Cloud SQL instance as well as
|
29
|
+
# the necessary database and user creation.
|
30
|
+
#
|
31
|
+
class CloudSQL
|
32
|
+
##
|
33
|
+
# Permits SQL admin operations with the Cloud SQL API.
|
34
|
+
SCOPES = ["https://www.googleapis.com/auth/sqlservice.admin"]
|
35
|
+
.freeze
|
36
|
+
|
37
|
+
##
|
38
|
+
# An alias for the SqladminV1beta4 module.
|
39
|
+
SQL = Google::Apis::SqladminV1beta4
|
40
|
+
|
41
|
+
##
|
42
|
+
# The name of the database used to store gemserver data.
|
43
|
+
# @return [String]
|
44
|
+
attr_reader :db
|
45
|
+
|
46
|
+
##
|
47
|
+
# The name of the default user created to access the database.
|
48
|
+
# @return [String]
|
49
|
+
attr_reader :user
|
50
|
+
|
51
|
+
##
|
52
|
+
# The password of the default user created to access the database.
|
53
|
+
# @return [String]
|
54
|
+
attr_reader :pwd
|
55
|
+
|
56
|
+
##
|
57
|
+
# The project ID of the project the gemserver will be deployed to.
|
58
|
+
# @return [String]
|
59
|
+
attr_reader :proj_id
|
60
|
+
|
61
|
+
##
|
62
|
+
# The name of the Cloud SQL instance.
|
63
|
+
# @return [String]
|
64
|
+
attr_reader :inst
|
65
|
+
|
66
|
+
##
|
67
|
+
# The Cloud SQL API used to manage Cloud SQL instances.
|
68
|
+
# @return [Google::Apis::SqladminV1beta4::SQLAdminService]
|
69
|
+
attr_reader :service
|
70
|
+
|
71
|
+
##
|
72
|
+
# Creates a CloudSQL object and loads the necessary configuration
|
73
|
+
# settings.
|
74
|
+
#
|
75
|
+
# @param inst [String] Name of the instance to be used. Optional.
|
76
|
+
def initialize inst = nil
|
77
|
+
auth = Google::Auth.get_application_default SCOPES
|
78
|
+
Google::Apis::RequestOptions.default.authorization = auth
|
79
|
+
@config = Configuration.new
|
80
|
+
@service = SQL::SQLAdminService.new
|
81
|
+
@inst = inst || "instance-#{SecureRandom.uuid}".freeze
|
82
|
+
@custom = inst ? true : false
|
83
|
+
load_config
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Prepares a Cloud SQL instance with a database and user. Also saves
|
88
|
+
# the database settings in the appropriate configuration file.
|
89
|
+
def run
|
90
|
+
create_instance do |instance_op|
|
91
|
+
run_sql_task instance_op if instance_op.class == SQL::Operation
|
92
|
+
update_root_user
|
93
|
+
create_db do |db_op|
|
94
|
+
run_sql_task db_op
|
95
|
+
create_user
|
96
|
+
end
|
97
|
+
end
|
98
|
+
update_config
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
##
|
104
|
+
# @private Creates a Cloud SQL instance.
|
105
|
+
def create_instance &block
|
106
|
+
if @custom
|
107
|
+
puts "Using existing Cloud SQL instance: #{@inst}"
|
108
|
+
yield
|
109
|
+
return instance
|
110
|
+
end
|
111
|
+
puts "Creating Cloud SQL instance #{@inst} (this takes a few "\
|
112
|
+
"minutes to complete)"
|
113
|
+
settings = SQL::Settings.new(tier: "db-f1-micro")
|
114
|
+
payload = SQL::DatabaseInstance.new(
|
115
|
+
name: @inst,
|
116
|
+
project: @proj_id,
|
117
|
+
settings: settings
|
118
|
+
)
|
119
|
+
@service.insert_instance(@proj_id, payload, &block)
|
120
|
+
end
|
121
|
+
|
122
|
+
##
|
123
|
+
# @private Creates a database for a Cloud SQL instance.
|
124
|
+
def create_db &block
|
125
|
+
puts "Creating database #{@db}"
|
126
|
+
db = SQL::Database.new name: @db
|
127
|
+
@service.insert_database(@proj_id, @inst, db, &block)
|
128
|
+
end
|
129
|
+
|
130
|
+
##
|
131
|
+
# @private Creates a user for a Cloud SQL instance.
|
132
|
+
def create_user
|
133
|
+
puts "Creating user #{@user}"
|
134
|
+
user = SQL::User.new(name: @user, password: @pwd)
|
135
|
+
run_sql_task @service.insert_user(@proj_id, @inst, user)
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# @private Updates the password of the root user if a new Cloud SQL
|
140
|
+
# instance was created.
|
141
|
+
def update_root_user
|
142
|
+
return if @custom
|
143
|
+
cmd = "gcloud sql users set-password root % --password #{@pwd} "\
|
144
|
+
"-i #{@inst} --project #{@proj_id}"
|
145
|
+
`#{cmd}`
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# @private Fetches a Cloud SQL instance.
|
150
|
+
#
|
151
|
+
# @return [Google::Apis::SqladminV1beta4::DatabaseInstance
|
152
|
+
def instance
|
153
|
+
@service.get_instance @proj_id, @inst
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Deletes the Cloud SQL instance for a gemserver.
|
158
|
+
def del_instance
|
159
|
+
puts "Deleting instance: #{@inst}"
|
160
|
+
@service.delete_instance @proj_id, @inst
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Sets various Cloud SQL settings used to create a Cloud SQL
|
165
|
+
# instance.
|
166
|
+
def load_config
|
167
|
+
@db = @config[:db_connection_options][:database]
|
168
|
+
@user = @config[:db_connection_options][:username]
|
169
|
+
@pwd = @config[:db_connection_options][:password]
|
170
|
+
@proj_id = @config[:proj_id]
|
171
|
+
end
|
172
|
+
|
173
|
+
##
|
174
|
+
# Saves the Cloud SQL configuration in the appropriate configuration
|
175
|
+
# file and app configuration file.
|
176
|
+
def update_config
|
177
|
+
puts "Updating configurations: app.yaml and config.yml "
|
178
|
+
conn_name = instance.connection_name
|
179
|
+
@config.update_config "/cloudsql/#{conn_name}",
|
180
|
+
:db_connection_options,
|
181
|
+
:socket
|
182
|
+
@config.update_app conn_name, "beta_settings", "cloud_sql_instances"
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Runs a Cloud SQL task and polls for its completion.
|
187
|
+
def run_sql_task op
|
188
|
+
while @service.get_operation(@proj_id, op.name).status != "DONE"
|
189
|
+
sleep 2
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Copyright 2017 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "google/cloud/gemserver"
|
16
|
+
require "google/cloud/resource_manager"
|
17
|
+
require "securerandom"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Gemserver
|
22
|
+
class CLI
|
23
|
+
##
|
24
|
+
# # Project
|
25
|
+
#
|
26
|
+
# Holds a reference to a project on Google Cloud Platform.
|
27
|
+
#
|
28
|
+
class Project
|
29
|
+
|
30
|
+
##
|
31
|
+
# The name of the project on Google Cloud platform; same as ID.
|
32
|
+
# @return [String]
|
33
|
+
attr_accessor :proj_name
|
34
|
+
|
35
|
+
##
|
36
|
+
# The Configuration object storing the settings used by the Project
|
37
|
+
# object.
|
38
|
+
# @return [Configuration]
|
39
|
+
attr_accessor :config
|
40
|
+
|
41
|
+
##
|
42
|
+
# Initializes the project name and Configuration object.
|
43
|
+
def initialize name = nil
|
44
|
+
@proj_name = name
|
45
|
+
@config = Configuration.new
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Fetches a reference to the given project on Google Cloud Platform
|
50
|
+
# and prompts the user to configure it correctly.
|
51
|
+
def create
|
52
|
+
raise "Project name was not provided!" unless @proj_name
|
53
|
+
begin
|
54
|
+
@config.update_config @proj_name, :proj_id
|
55
|
+
create_gae_project
|
56
|
+
enable_api
|
57
|
+
enable_billing
|
58
|
+
project
|
59
|
+
rescue Google::Cloud::PermissionDeniedError, RuntimeError => e
|
60
|
+
puts "Permission denied. You might not be authorized with " \
|
61
|
+
"gcloud. Read github.com/GoogleCloudPlatform/google-cloud`." \
|
62
|
+
"-ruby/google-cloud-gemserver/docs/authentication.md for " \
|
63
|
+
"more information on how to get authenticated."
|
64
|
+
puts "If you still get this error the Cloud Resource Manager " \
|
65
|
+
"API might not be enabled."
|
66
|
+
abort "More details: #{e.message}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
##
|
73
|
+
# @private Checks if the current Google Cloud Platform project
|
74
|
+
# contains a Google App Engine project. If not, one is created.
|
75
|
+
def create_gae_project
|
76
|
+
return if project_exists?
|
77
|
+
puts "Required Google App Engine project does not exist."
|
78
|
+
system "gcloud app create --project #{@proj_name}"
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# @private Checks if a Google App Engine project exists.
|
83
|
+
#
|
84
|
+
# @return [Boolean]
|
85
|
+
def project_exists?
|
86
|
+
system "gcloud app describe --project #{@proj_name} >/dev/null 2>&1"
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# @private Prompts the user to press enter.
|
91
|
+
#
|
92
|
+
# @return [String]
|
93
|
+
def prompt_user
|
94
|
+
puts "\nPress enter to continue..."
|
95
|
+
STDIN.gets
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# @private Fetches a given project on Google Cloud Platform.
|
100
|
+
#
|
101
|
+
# @return [Google::Cloud::ResourceManager::Project]
|
102
|
+
def project
|
103
|
+
resource_manager = Google::Cloud::ResourceManager.new
|
104
|
+
resource_manager.project @proj_name
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# @private Prompts the user to enable necessary APIs for the
|
109
|
+
# gemserver to work as intended.
|
110
|
+
#
|
111
|
+
# @return [String]
|
112
|
+
def enable_api
|
113
|
+
puts "\nEnable the Google Cloud SQL API if it is not already "\
|
114
|
+
"enabled by visiting:\n https://console.developers.google.com"\
|
115
|
+
"/apis/api/sqladmin.googleapis.com/overview?"\
|
116
|
+
"project=#{@proj_name} and clicking \"Enable\""
|
117
|
+
puts "\nEnable the Google Cloud Resource manager API if it is not"\
|
118
|
+
"already enabled by visiting:\nhttps://console.developers.google"\
|
119
|
+
".com/apis/api/cloudresourcemanager.googleapis.com/overview?"\
|
120
|
+
"project=#{@proj_name} and clicking \"Enable\""
|
121
|
+
puts "\nEnable the Google App Engine Admin API if it is not "\
|
122
|
+
"already enabled by visiting:\nhttps://console.developers.google"\
|
123
|
+
".com/apis/api/appengine.googleapis.com/overview?"\
|
124
|
+
"project=#{@proj_name} and clicking \"Enable\""
|
125
|
+
prompt_user
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# @private Prompts the user to enable billing such that the gemserver
|
130
|
+
# work as intended.
|
131
|
+
#
|
132
|
+
# @return [String]
|
133
|
+
def enable_billing
|
134
|
+
puts "\nEnable billing for the project you just created by "\
|
135
|
+
"visiting: \nconsole.cloud.google.com/billing?project="\
|
136
|
+
"#{@proj_name}\nand setting up a billing account."
|
137
|
+
prompt_user
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# Copyright 2017 Google Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# @https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
require "google/cloud/gemserver"
|
16
|
+
require "net/http"
|
17
|
+
require "yaml"
|
18
|
+
|
19
|
+
module Google
|
20
|
+
module Cloud
|
21
|
+
module Gemserver
|
22
|
+
class CLI
|
23
|
+
##
|
24
|
+
#
|
25
|
+
# # Request
|
26
|
+
#
|
27
|
+
# Responsible for sending requests to the gemserver for operations that
|
28
|
+
# involve the database. Gem operations are done with the 'gem' command
|
29
|
+
# and are not in the scope of Request.
|
30
|
+
class Request
|
31
|
+
|
32
|
+
##
|
33
|
+
# The HTTP object used to connect to and send requests to the
|
34
|
+
# gemserver.
|
35
|
+
# @return [Net::HTTP]
|
36
|
+
attr_accessor :http
|
37
|
+
|
38
|
+
##
|
39
|
+
# Initialize the Backend object by constructing an HTTP object for the
|
40
|
+
# gemserver.
|
41
|
+
#
|
42
|
+
# @param [String] url The URL of the gemserver. Optional.
|
43
|
+
#
|
44
|
+
# @param [String] proj_name The name of the Google Cloud Platform the
|
45
|
+
# gemserver was deployed to. Optional.
|
46
|
+
def initialize url = nil, proj_name = nil
|
47
|
+
gemserver_url = url.nil? == true ? remote(proj_name) : url
|
48
|
+
@http = Net::HTTP.new gemserver_url
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Send a request to the gemserver to create a key with certain
|
53
|
+
# permissions.
|
54
|
+
#
|
55
|
+
# @param [String] permissions The permissions the generated key will
|
56
|
+
# have (read, write, or both). Optional.
|
57
|
+
#
|
58
|
+
# @return [Net::HTTPResponse]
|
59
|
+
def create_key permissions = nil
|
60
|
+
send_req Net::HTTP::Post, "/api/v1/key", {permissions: permissions}
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Send a request to the gemserver to delete a key.
|
65
|
+
#
|
66
|
+
# @param [String] key The key to delete.
|
67
|
+
#
|
68
|
+
# @return [Net::HTTPResponse]
|
69
|
+
def delete_key key
|
70
|
+
send_req Net::HTTP::Put, "/api/v1/key", {key: key}
|
71
|
+
end
|
72
|
+
|
73
|
+
##
|
74
|
+
# Send a request to the gemserver to fetch information about stored
|
75
|
+
# private gems and cached gem dependencies.
|
76
|
+
#
|
77
|
+
# @return [Net::HTTPResponse]
|
78
|
+
def stats
|
79
|
+
send_req Net::HTTP::Post, "/api/v1/stats"
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Sends a request to the gemserver to ensure it is accessible.
|
84
|
+
#
|
85
|
+
# @return [Net::HTTPResponse]
|
86
|
+
def health
|
87
|
+
send_req Net::HTTP::Get, "/health"
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
##
|
93
|
+
# @private The URL of the gemserver.
|
94
|
+
#
|
95
|
+
# @param [String] proj_name The Google Cloud Platform project the
|
96
|
+
# gemserver was deployed to.
|
97
|
+
#
|
98
|
+
# @return [String]
|
99
|
+
def remote proj_name
|
100
|
+
descrip = YAML.load(`gcloud app describe --project #{proj_name}`)
|
101
|
+
descrip["defaultHostname"]
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# @private Makes a request to the gemserver and returns the response.
|
106
|
+
#
|
107
|
+
# @param [Net::HTTP] type The type of HTTP request.
|
108
|
+
#
|
109
|
+
# @param [String] endpoint The endpoint the request is made to on the
|
110
|
+
# gemserver.
|
111
|
+
#
|
112
|
+
# @param [Object] params The data passed to the gemserver to be
|
113
|
+
# processed. Optional.
|
114
|
+
#
|
115
|
+
# @return [String]
|
116
|
+
def send_req type, endpoint, params = nil
|
117
|
+
auth = Google::Cloud::Gemserver::Authentication.new
|
118
|
+
t = auth.access_token["access_token"]
|
119
|
+
req = type.new endpoint
|
120
|
+
req["Authorization"] = Signet::OAuth2.generate_bearer_authorization_header t
|
121
|
+
if type != Net::HTTP::Get
|
122
|
+
req.set_form_data(params) if params
|
123
|
+
end
|
124
|
+
@http.request req
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|