class Google::Cloud::Gemserver::CLI::Server
# Server
Object responsible for deploying the gemserver to Google
Cloud
Platform and starting it.
Attributes
The Configuration
object used to deploy the gemserver @return [Configuration]
Public Class Methods
Creates a Server
instance by initializing a Configuration
object that will be used to access paths to necessary configuration files.
# File lib/google/cloud/gemserver/cli/server.rb, line 40 def initialize @config = Configuration.new end
Public Instance Methods
Deletes a given gemserver by its parent project's ID.
@param [String] proj_id The project ID of the project the gemserver was deployed to.
# File lib/google/cloud/gemserver/cli/server.rb, line 90 def delete proj_id return unless Configuration.deployed? full_delete = user_input("This will delete the entire Google Cloud"\ " Platform project #{proj_id}. Continue"\ " deletion? (Y|n, default n) If no, all relevant resources will"\ " be deleted besides the parent GCP project.").downcase if full_delete == "y" puts "Deleting gemserver with parent project" system "gcloud projects delete #{proj_id}" else @config.delete_from_cloud del_gcs_files inst = @config.app["beta_settings"]["cloud_sql_instances"] .split(":").pop puts "Deleting child Cloud SQL instance #{inst}..." params = "delete #{inst} --project #{proj_id}" status = system "gcloud beta sql instances #{params}" fail "Unable to delete instance" unless status puts "The Cloud SQL instance has been deleted. Visit:\n "\ "https://console.cloud.google.com/appengine/settings?project="\ "#{proj_id} and click \"Disable Application\" to delete the "\ "Google App Engine application the gemserver was deployed to." end end
Deploys the gemserver to Google
Cloud
Platform if the app environment variable is set to “production.” Otherwise, the gemserver is started locally.
# File lib/google/cloud/gemserver/cli/server.rb, line 66 def deploy begin return start if ["test", "dev"].include? ENV["APP_ENV"] deploy_to_gae setup_default_keys ensure cleanup end end
Starts the gemserver by starting up the gemstash server with predefined options.
# File lib/google/cloud/gemserver/cli/server.rb, line 47 def start path = if ENV["APP_ENV"] == "production" Configuration::GAE_PATH else @config.config_path end args = [ "start", "--no-daemonize", "--config-file=#{path}" ].freeze Google::Cloud::Gemserver::Backend::StorageSync.download_service Google::Cloud::Gemserver::Backend::GemstashServer.start args end
Private Instance Methods
@private Deletes the temporary directory containing the files used to deploy the gemserver.
# File lib/google/cloud/gemserver/cli/server.rb, line 311 def cleanup FileUtils.rm_rf Configuration::SERVER_PATH end
Deploys the gemserver to Google
App Engine and uploads the configuration file used by the gemserver to Google
Cloud
Storage for later convenience.
# File lib/google/cloud/gemserver/cli/server.rb, line 121 def deploy_to_gae puts "Beginning gemserver deployment..." prepare_dir path = "#{Configuration::SERVER_PATH}/app.yaml" flags = "-q --project #{@config[:proj_id]}" status = system "gcloud app deploy #{path} #{flags}" fail "Gemserver deployment failed. " unless status wait_until_server_accessible @config.save_to_cloud display_next_steps end
@private Outputs helpful information to the console indicating the URL the gemserver is running at and how to use the gemserver.
# File lib/google/cloud/gemserver/cli/server.rb, line 220 def display_next_steps puts "\nThe gemserver has been deployed! It is running on #{remote}" puts "\nTo see the status of the gemserver, visit: \n" \ " #{remote}/health" puts "\nTo see how to use your gemserver to push and download " \ "gems read https://github.com/GoogleCloudPlatform/google-cloud-" \ "gemserver/blob/master/docs/usage_example.md for some examples." puts "\nFor general information, visit https://github.com/" \ "GoogleCloudPlatform/google-cloud-gemserver/blob/master/README.md" end
@private Creates a Gemfile and Gemfile.lock for the gemserver that runs on Google
App Engine such that gemstash is not required client side for the CLI
.
# File lib/google/cloud/gemserver/cli/server.rb, line 284 def gemfile File.open("#{Configuration::SERVER_PATH}/Gemfile", "w") do |f| f.write gemfile_source end require "bundler" Bundler.with_clean_env do run_cmd "cd #{Configuration::SERVER_PATH} && bundle lock" end end
@private The Gemfile used by the gemserver on Google
App Engine.
@return [String]
# File lib/google/cloud/gemserver/cli/server.rb, line 265 def gemfile_source <<~SOURCE source "https://rubygems.org" gem "google-cloud-gemserver", "#{Google::Cloud::Gemserver::VERSION}", path: "." gem "concurrent-ruby", require: "concurrent" gem "gemstash", git: "https://github.com/bundler/gemstash.git", ref: "a5a78e2" gem "mysql2", "~> 0.4" gem "filelock", "~> 1.1.1" gem "google-cloud-storage", "~> 1.1.0" gem "google-cloud-resource_manager", "~> 0.24" gem "activesupport", "~> 4.2" SOURCE end
@private Creates a temporary directory with the necessary files to deploy the gemserver.
# File lib/google/cloud/gemserver/cli/server.rb, line 298 def prepare_dir dir = Gem::Specification.find_by_name(Configuration::GEM_NAME).gem_dir cleanup if Dir.exist? Configuration::SERVER_PATH FileUtils.mkpath Configuration::SERVER_PATH FileUtils.cp_r "#{dir}/.", Configuration::SERVER_PATH FileUtils.cp @config.config_path, Configuration::SERVER_PATH FileUtils.cp @config.app_path, Configuration::SERVER_PATH gemfile end
@private The URL of the gemserver.
@return [String]
# File lib/google/cloud/gemserver/cli/server.rb, line 255 def remote flag = "--project #{@config[:proj_id]}" descrip = YAML.load(run_cmd "gcloud app describe #{flag}") descrip["defaultHostname"] end
@private Runs a given command on the local machine.
@param [String] args The command to be run.
# File lib/google/cloud/gemserver/cli/server.rb, line 319 def run_cmd args `#{args}` end
@private Sanitizes a name by removing special symbols and ensuring it is alphanumeric (and hyphens, underscores).
@param [String] name The name to be sanitized.
@return [String]
# File lib/google/cloud/gemserver/cli/server.rb, line 212 def sanitize_name name name = name.chomp name.gsub(/[^0-9a-z\-\_]/i, "") end
@private Sets a given key in the bundle config used by bundler for installing gems.
@param [String] key The key to be added to the bundle config. @param [String] gemserver_url The URL of the gemserver.
# File lib/google/cloud/gemserver/cli/server.rb, line 164 def set_bundle key, gemserver_url puts "Updating bundle config" run_cmd "bundle config http://#{gemserver_url}/private #{key}" end
@private Sets a given key in the gem credentials file used by Rubygems.org
@param [String] key The key to be added to the credentials.
# File lib/google/cloud/gemserver/cli/server.rb, line 174 def set_gem_credentials key key_name = sanitize_name(user_input("Updating bundle config. Enter"\ " a name for your key (default is \"master-gemserver-key\"")) key_name = key_name.empty? == true ? Configuration::DEFAULT_KEY_NAME : key_name puts "Updating #{Configuration::CREDS_PATH}" FileUtils.touch Configuration::CREDS_PATH keys = YAML.load_file(Configuration::CREDS_PATH) || {} if keys[key_name.to_sym].nil? system "echo \":#{key_name}: #{key}\" >> #{Configuration::CREDS_PATH}" else puts "The key name \"#{key_name}\" already exists. Please update"\ " #{Configuration::CREDS_PATH} manually to replace the key or" \ " manually enter a different name into the file for your key:" \ " #{key}." end end
@private Creates a key with all permissions and sets it in the necessary configurations (gem credentials and bundle config).
# File lib/google/cloud/gemserver/cli/server.rb, line 144 def setup_default_keys should_create = user_input("Would you like to setup a default " \ "key? [Y/n] (default yes)") return if should_create.downcase == "n" gemserver_url = remote res = Request.new(gemserver_url).create_key abort "Error generating key" unless res.code.to_i == 200 key = Backend::Key.send :parse_key, res.body abort "Invalid key" unless valid_key? key puts "Generated key: #{key}" set_bundle key, gemserver_url set_gem_credentials key end
@private Gets input from the user after displaying a message.
@param [String] msg The message to be displayed.
@return [String]
# File lib/google/cloud/gemserver/cli/server.rb, line 329 def user_input msg puts msg STDIN.gets.chomp end
@private Checks if a key is valid by its length and value.
@param [String] key The key to be validated.
@return [Boolean]
# File lib/google/cloud/gemserver/cli/server.rb, line 199 def valid_key? key size = key.size == Backend::Key::KEY_LENGTH m_size = key.gsub(/[^0-9a-z]/i, "").size == Backend::Key::KEY_LENGTH size && m_size end
@private Pings the gemserver until a timeout or the gemserver replies with a 200 response code.
@param [Integer] timeout The length of time the gemserver is pinged. Optional.
# File lib/google/cloud/gemserver/cli/server.rb, line 237 def wait_until_server_accessible timeout = 60 puts "Waiting for the gemserver to be accessible..." start_time = Time.now loop do if Time.now - start_time > timeout fail "Could not establish a connection to the gemserver" else r = Request.new(nil, @config[:proj_id]).health break if r.code.to_i == 200 end sleep 5 end end