Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small improvements #83

Merged
merged 6 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ _Please add entries here for your pull requests that are not yet released._

- Fixed failed build on MacOS by adding platform flag and fixed multiple files in yaml document for template. [PR 81](https://github.com/shakacode/heroku-to-control-plane/pull/81) by [justin808](https://github.com/justin808).

### Added

rafaelgomesxyz marked this conversation as resolved.
Show resolved Hide resolved
- Added `open-console` command to open the app console on Control Plane. [PR 83](https://github.com/shakacode/heroku-to-control-plane/pull/83) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
- Added option to set the org with a `CPLN_ORG` env var. [PR 83](https://github.com/shakacode/heroku-to-control-plane/pull/83) by [Rafael Gomes](https://github.com/rafaelgomesxyz).
- Added `--verbose` option to all commands for more detailed logs. [PR 83](https://github.com/shakacode/heroku-to-control-plane/pull/83) by [Rafael Gomes](https://github.com/rafaelgomesxyz).

### Changed

- Calling `cpl` with no command now shows the help menu. [PR 83](https://github.com/shakacode/heroku-to-control-plane/pull/83) by [Rafael Gomes](https://github.com/rafaelgomesxyz).

## [1.1.1] - 2023-09-23

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ For the typical Rails app, this means:

## Installation

1. Ensure your [Control Plane](https://controlplane.com) account is set up. Set up an `organization` <your-org> for testing in that account and modify the value for `aliases.common.cpln_org` in `.controlplane/controlplane.yml`. If you need an organization, please [contact Shakacode](mailto:[email protected]).
1. Ensure your [Control Plane](https://controlplane.com) account is set up. Set up an `organization` <your-org> for testing in that account and modify the value for `aliases.common.cpln_org` in `.controlplane/controlplane.yml`, or you can also set it with the `CPLN_ORG` environment variable. If you need an organization, please [contact Shakacode](mailto:[email protected]).

2. Install [Node.js](https://nodejs.org/en) (required for Control Plane CLI).

Expand Down Expand Up @@ -138,7 +138,7 @@ The `cpl` gem is based on several configuration files within a `/.controlplane`
├─ entrypoint.sh
```

1. `controlplane.yml` describes the overall application. Be sure to have <your-org> as the value for `aliases.common.cpln_org`.
1. `controlplane.yml` describes the overall application. Be sure to have <your-org> as the value for `aliases.common.cpln_org`, or set it with the `CPLN_ORG` environment variable.
2. `Dockerfile` builds the production application. `entrypoint.sh` is an _example_ entrypoint script for the production application, referenced in your Dockerfile.
3. `templates` directory contains the templates for the various workloads, such as `rails.yml` and `postgres.yml`.
4. `templates/gvc.yml` defines your project's GVC (like a Heroku app). More importantly, it contains ENV values for the app.
Expand Down
9 changes: 9 additions & 0 deletions docs/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,15 @@ cpl open -a $APP_NAME
cpl open -a $APP_NAME -w $WORKLOAD_NAME
```

### `open-console`

- Opens the app console on Control Plane in the default browser
- Can also go directly to a workload page if `--workload` is provided

```sh
cpl open-console -a $APP_NAME
```

### `promote-app-from-upstream`

- Copies the latest image from upstream, runs a release script (optional), and deploys the image
Expand Down
12 changes: 12 additions & 0 deletions lib/command/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@ def self.wait_option(title = "", required: false)
}
end

def self.verbose_option(required: false)
{
name: :verbose,
params: {
aliases: ["-d"],
desc: "Shows detailed logs",
type: :boolean,
required: required
}
}
end

def self.all_options
methods.grep(/_option$/).map { |method| send(method.to_s) }
end
Expand Down
5 changes: 5 additions & 0 deletions lib/command/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ class Config < Base
EX

def call # rubocop:disable Metrics/MethodLength
if config.org_comes_from_env
puts Shell.color("Org comes from CPLN_ORG env var", :yellow)
rafaelgomesxyz marked this conversation as resolved.
Show resolved Hide resolved
puts
end

if config.app
puts "#{Shell.color("Current config (app '#{config.app}')", :blue)}:"
puts pretty_print(config.current)
Expand Down
7 changes: 5 additions & 2 deletions lib/command/copy_image_from_upstream.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def call # rubocop:disable Metrics/MethodLength
ensure_docker_running!

@upstream = config[:upstream]
@upstream_org = config.apps[@upstream.to_sym][:cpln_org]
@upstream_org = config.apps[@upstream.to_sym][:cpln_org] || ENV.fetch("CPLN_ORG_UPSTREAM", nil)
ensure_upstream_org!

create_upstream_profile
Expand All @@ -51,7 +51,10 @@ def ensure_docker_running!
end

def ensure_upstream_org!
raise "Can't find option 'cpln_org' for app '#{@upstream}' in 'controlplane.yml'." unless @upstream_org
return if @upstream_org

raise "Can't find option 'cpln_org' for app '#{@upstream}' in 'controlplane.yml', " \
"and CPLN_ORG_UPSTREAM env var is not set."
end

def create_upstream_profile
Expand Down
7 changes: 5 additions & 2 deletions lib/command/info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,17 +81,20 @@ def fetch_app_workloads(org) # rubocop:disable Metrics/MethodLength
end
end

def orgs # rubocop:disable Metrics/MethodLength
def orgs # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
result = []

if config.options[:org]
result.push(config.options[:org])
else
org_from_env = ENV.fetch("CPLN_ORG", nil)
result.push(org_from_env) if org_from_env

config.apps.each do |app_name, app_options|
next if config.app && !app_matches?(config.app, app_name, app_options)

org = app_options[:cpln_org]
result.push(org) unless result.include?(org)
result.push(org) if org && !result.include?(org)
end
end

Expand Down
8 changes: 5 additions & 3 deletions lib/command/no_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ class NoCommand < Base
HIDE = true

def call
return unless config.options[:version]

Cpl::Cli.start(["version"])
if config.options[:version]
Cpl::Cli.start(["version"])
else
Cpl::Cli.start(["help"])
end
end
end
end
26 changes: 26 additions & 0 deletions lib/command/open_console.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module Command
class OpenConsole < Base
NAME = "open-console"
OPTIONS = [
app_option(required: true),
workload_option
].freeze
DESCRIPTION = "Opens the app console on Control Plane in the default browser"
LONG_DESCRIPTION = <<~DESC
- Opens the app console on Control Plane in the default browser
- Can also go directly to a workload page if `--workload` is provided
DESC

def call
workload = config.options[:workload]
url = "https://console.cpln.io/console/org/#{config.org}/gvc/#{config.app}"
url += "/workload/#{workload}" if workload
url += "/-info"
opener = `which xdg-open open`.split("\n").grep_v("not found").first

exec %(#{opener} "#{url}")
end
end
end
23 changes: 20 additions & 3 deletions lib/core/config.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# frozen_string_literal: true

class Config
class Config # rubocop:disable Metrics/ClassLength
attr_reader :config, :current,
:org, :app, :apps, :app_dir,
:org, :org_comes_from_env, :app, :apps, :app_dir,
# command line options
:args, :options

Expand All @@ -12,10 +12,13 @@ def initialize(args, options)
@args = args
@options = options
@org = options[:org]
@org_comes_from_env = false
@app = options[:app]

load_app_config
load_apps

Shell.verbose_mode(options[:verbose])
end

def [](key)
Expand Down Expand Up @@ -48,6 +51,13 @@ def ensure_current_config_app!(app_name)
raise "Can't find app '#{app_name}' in 'controlplane.yml'." unless current
end

def ensure_current_config_org!(app_name)
return if @org

raise "Can't find option 'cpln_org' for app '#{app_name}' in 'controlplane.yml', " \
"and CPLN_ORG env var is not set."
end

def ensure_config!
raise "'controlplane.yml' is empty." unless config
end
Expand All @@ -66,8 +76,15 @@ def app_matches_current?(app_name, app_options)

def pick_current_config(app_name, app_options)
@current = app_options
@org = self[:cpln_org]
ensure_current_config_app!(app_name)

if current.key?(:cpln_org)
@org = current.fetch(:cpln_org)
else
@org = ENV.fetch("CPLN_ORG", nil)
@org_comes_from_env = true
end
ensure_current_config_org!(app_name)
end

def load_apps # rubocop:disable Metrics/MethodLength
Expand Down
35 changes: 25 additions & 10 deletions lib/core/controlplane.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ def profile_exists?(profile)

def profile_create(profile, token)
cmd = "cpln profile create #{profile} --token #{token}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

def profile_delete(profile)
cmd = "cpln profile delete #{profile}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

Expand Down Expand Up @@ -61,25 +61,25 @@ def image_delete(image)

def image_login(org_name = config.org)
cmd = "cpln image docker-login --org #{org_name}"
cmd += " > /dev/null 2>&1" if Shell.tmp_stderr
cmd += " > /dev/null 2>&1" if Shell.should_hide_output?
perform!(cmd)
end

def image_pull(image)
cmd = "docker pull #{image}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

def image_tag(old_tag, new_tag)
cmd = "docker tag #{old_tag} #{new_tag}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

def image_push(image)
cmd = "docker push #{image}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

Expand Down Expand Up @@ -148,7 +148,11 @@ def workload_get_replicas(workload, location:)
end

def workload_get_replicas_safely(workload, location:)
cmd = "cpln workload get-replicas #{workload} #{gvc_org} --location #{location} -o yaml 2> /dev/null"
cmd = "cpln workload get-replicas #{workload} #{gvc_org} --location #{location} -o yaml"
cmd += " 2> /dev/null" if Shell.should_hide_output?

Shell.debug("CMD", cmd)

result = `#{cmd}`
$CHILD_STATUS.success? ? YAML.safe_load(result) : nil
end
Expand Down Expand Up @@ -180,7 +184,7 @@ def workload_deployments_ready?(workload, expected_status:)
def workload_set_image_ref(workload, container:, image:)
cmd = "cpln workload update #{workload} #{gvc_org}"
cmd += " --set spec.containers.#{container}.image=/org/#{config.org}/image/#{image}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

Expand Down Expand Up @@ -208,7 +212,7 @@ def set_workload_suspend(workload, value)

def workload_force_redeployment(workload)
cmd = "cpln workload force-redeployment #{workload} #{gvc_org}"
cmd += " > /dev/null" if Shell.tmp_stderr
cmd += " > /dev/null" if Shell.should_hide_output?
perform!(cmd)
end

Expand Down Expand Up @@ -282,10 +286,15 @@ def apply_template(data) # rubocop:disable Metrics/MethodLength
f.rewind
cmd = "cpln apply #{gvc_org} --file #{f.path}"
if Shell.tmp_stderr
cmd += " 2> #{Shell.tmp_stderr.path}"
cmd += " 2> #{Shell.tmp_stderr.path}" if Shell.should_hide_output?

Shell.debug("CMD", cmd)

result = `#{cmd}`
$CHILD_STATUS.success? ? parse_apply_result(result) : false
else
Shell.debug("CMD", cmd)

result = `#{cmd}`
$CHILD_STATUS.success? ? parse_apply_result(result) : exit(false)
end
Expand Down Expand Up @@ -332,14 +341,20 @@ def parse_apply_result(result) # rubocop:disable Metrics/CyclomaticComplexity, M
private

def perform(cmd)
Shell.debug("CMD", cmd)

system(cmd)
end

def perform!(cmd)
Shell.debug("CMD", cmd)

system(cmd) || exit(false)
end

def perform_yaml(cmd)
Shell.debug("CMD", cmd)

result = `#{cmd}`
$CHILD_STATUS.success? ? YAML.safe_load(result) : exit(false)
end
Expand Down
2 changes: 2 additions & 0 deletions lib/core/controlplane_api_direct.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def call(url, method:, host: :api, body: nil) # rubocop:disable Metrics/MethodLe
request["Authorization"] = api_token
request.body = body.to_json if body

Shell.debug(method.upcase, "#{uri} #{body&.to_json}")

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https") { |http| http.request(request) }

case response
Expand Down
14 changes: 13 additions & 1 deletion lib/core/shell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class Shell
class << self
attr_reader :tmp_stderr
attr_reader :tmp_stderr, :verbose
end

def self.shell
Expand Down Expand Up @@ -50,4 +50,16 @@ def self.warn_deprecated(message)
def self.abort(message)
Kernel.abort(color("ERROR: #{message}", :red))
end

def self.verbose_mode(verbose)
@verbose = verbose
end

def self.debug(prefix, message)
stderr.puts("\n[#{color(prefix, :red)}] #{message}") if verbose
end

def self.should_hide_output?
tmp_stderr && !verbose
end
end
2 changes: 1 addition & 1 deletion lib/cpl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def self.all_base_commands
usage = command_class::USAGE.empty? ? name : command_class::USAGE
requires_args = command_class::REQUIRES_ARGS
default_args = command_class::DEFAULT_ARGS
command_options = command_class::OPTIONS
command_options = command_class::OPTIONS + [::Command::Base.verbose_option]
description = command_class::DESCRIPTION
long_description = command_class::LONG_DESCRIPTION
examples = command_class::EXAMPLES
Expand Down