cf 4.0.1.rc2 → 4.1.0rc1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3f7db873a3433f6a41a5b6b2373560e6638651e2
4
+ data.tar.gz: ee5511a3f2188b76047fe98e7d5b40de804e36da
5
+ SHA512:
6
+ metadata.gz: e587cae8a1feef4fc85c5ab0f691449d692376c5c16ebe587a75afa3cdd4deed45227cdda180947d7103d431dd35eb068ac8e3ceaa4891d3e5222be6cac61a56
7
+ data.tar.gz: 1f6e73117e955a892551126c3c52069a9856e8d5aa2ce2e122fc061d6cc66d6f2bd65d253956671f6780cb898c347e2ca1a90289021df2453b59805130ccd60f
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "rake"
2
2
  require "rspec/core/rake_task"
3
+ Dir.glob("lib/tasks/**/*").sort.each { |ext| load(ext) }
3
4
 
4
5
  specfile, _ = Dir["*.gemspec"]
5
6
  SPEC = Gem::Specification.load(specfile)
data/lib/cf.rb CHANGED
@@ -11,3 +11,4 @@ require "admin/plugin"
11
11
  require "console/plugin"
12
12
  require "tunnel/plugin"
13
13
  require "manifests/plugin"
14
+ require "micro/plugin"
@@ -14,6 +14,7 @@ require "cf/spacing"
14
14
 
15
15
  require "cf/cli/help"
16
16
  require "cf/cli/interactive"
17
+ require "cf/cli/login_requirements"
17
18
 
18
19
 
19
20
  $cf_asked_auth = false
@@ -72,6 +73,7 @@ module CF
72
73
  end
73
74
 
74
75
  def check_logged_in
76
+ check_target
75
77
  unless client.logged_in?
76
78
  if force?
77
79
  fail "Please log in with 'cf login'."
@@ -84,17 +86,42 @@ module CF
84
86
  end
85
87
  end
86
88
 
87
- def precondition
88
- check_target
89
- check_logged_in
89
+ desc "Help!"
90
+ input :command, :argument => :optional
91
+ input :all, :type => :boolean
92
+ def help
93
+ if name = input[:command]
94
+ if cmd = @@commands[name.gsub("-", "_").to_sym]
95
+ Mothership::Help.command_help(cmd)
96
+ else
97
+ unknown_command(name)
98
+ end
99
+ elsif Help.has_groups?
100
+ unless input[:all]
101
+ puts "#{help_header}"
102
+ end
90
103
 
91
- unless client.current_organization
92
- fail "Please select an organization with 'cf target --organization ORGANIZATION_NAME'. (Get organization names from 'cf orgs'.)"
104
+ Mothership::Help.print_help_groups(@@global, input[:all])
105
+ else
106
+ Mothership::Help.basic_help(@@commands, @@global)
93
107
  end
108
+ end
94
109
 
95
- unless client.current_space
96
- fail "Please select a space with 'cf target --space SPACE_NAME'. (Get space names from 'cf spaces'.)"
97
- end
110
+ def help_header
111
+ <<EOS
112
+ Cloud Foundry Command Line Interface, version [#{CF::VERSION}]
113
+ Showing basic commands. Use 'cf help --all' to list all commands, or
114
+ 'cf help [command]' for help detailed help on a command.
115
+
116
+ For docs and support visit http://support.cloudfoundry.com
117
+
118
+ USAGE EXAMPLES
119
+ $ cf target api.run.pivotal.io <-- sets target API endpoint (the CF instance where you want to push apps) to 'api.run.pivotal.io'
120
+ $ cf login <-- logs into currently targeted CF instance, will also prompt for target org and app space
121
+ $ cf push <-- deploys app to current target
122
+ $ cf target -s staging <-- changes currently targeted app space to 'staging'
123
+
124
+ EOS
98
125
  end
99
126
 
100
127
  def wrap_errors
@@ -160,7 +187,7 @@ module CF
160
187
  else
161
188
  wrap_errors do
162
189
  @command = cmd
163
- precondition
190
+ precondition if respond_to? :precondition
164
191
 
165
192
  save_token_if_it_changes do
166
193
  super
@@ -3,6 +3,8 @@ require "cf/cli"
3
3
  module CF
4
4
  module App
5
5
  class Base < CLI
6
+ include LoginRequirements
7
+
6
8
  # choose the right color for app/instance state
7
9
  def state_color(s)
8
10
  case s
@@ -3,6 +3,7 @@ require "cf/cli"
3
3
  module CF
4
4
  module Domain
5
5
  class Base < CLI
6
+ include LoginRequirements
6
7
  end
7
8
  end
8
9
  end
@@ -0,0 +1,13 @@
1
+ module LoginRequirements
2
+ def precondition
3
+ check_logged_in
4
+
5
+ unless client.current_organization
6
+ fail "Please select an organization with 'cf target --organization ORGANIZATION_NAME'. (Get organization names from 'cf orgs'.)"
7
+ end
8
+
9
+ unless client.current_space
10
+ fail "Please select a space with 'cf target --space SPACE_NAME'. (Get space names from 'cf spaces'.)"
11
+ end
12
+ end
13
+ end
@@ -3,6 +3,8 @@ require "cf/cli"
3
3
  module CF
4
4
  module Populators
5
5
  class Base < CF::CLI
6
+ include LoginRequirements
7
+
6
8
  attr_reader :input, :info
7
9
 
8
10
  def initialize(input)
@@ -3,6 +3,7 @@ require "cf/cli"
3
3
  module CF
4
4
  module Route
5
5
  class Base < CLI
6
+ include LoginRequirements
6
7
  end
7
8
  end
8
9
  end
@@ -2,8 +2,6 @@ require "cf/cli/route/base"
2
2
 
3
3
  module CF::Route
4
4
  class Map < Base
5
- def precondition; end
6
-
7
5
  desc "Add a URL mapping"
8
6
  group :apps, :info, :hidden => true
9
7
  input :app, :desc => "Application to add the URL to",
@@ -3,6 +3,7 @@ require "cf/cli"
3
3
  module CF
4
4
  module Service
5
5
  class Base < CLI
6
+ include LoginRequirements
6
7
  end
7
8
  end
8
9
  end
@@ -3,6 +3,7 @@ require "cf/cli"
3
3
  module CF
4
4
  module Start
5
5
  class Base < CLI
6
+
6
7
  # Make sure we only show the target once
7
8
  @@displayed_target = false
8
9
 
@@ -10,11 +11,6 @@ module CF
10
11
  @@displayed_target
11
12
  end
12
13
 
13
-
14
- # These commands don't require authentication.
15
- def precondition;
16
- end
17
-
18
14
  private
19
15
 
20
16
  def show_context
@@ -1,3 +1,3 @@
1
1
  module CF
2
- VERSION = "4.0.1.rc2".freeze
2
+ VERSION = "4.1.0rc1".freeze
3
3
  end
@@ -7,32 +7,21 @@ module CFManifests
7
7
  MANIFEST_FILE = "manifest.yml"
8
8
 
9
9
  @@showed_manifest_usage = false
10
-
11
- class BadManifestError < StandardError
12
-
13
- def initialize(attr)
14
- @attr = attr
15
- end
16
-
17
- def to_s
18
- "#{@attr} is not a valid attribute, please visit the Manifest " +
19
- "Documentation for a list of valid attributes."
20
- end
21
- end
10
+ @@manifest = nil
22
11
 
23
12
  def manifest
24
- return @manifest if @manifest
13
+ return @@manifest if @@manifest
25
14
 
26
15
  if manifest_file && File.exists?(manifest_file)
27
- @manifest = load_manifest(manifest_file)
16
+ @@manifest = load_manifest(manifest_file)
28
17
  end
29
18
  end
30
19
 
31
20
  def save_manifest(save_to = manifest_file)
32
- fail "No manifest to save!" unless @manifest
21
+ fail "No manifest to save!" unless @@manifest
33
22
 
34
23
  File.open(save_to, "w") do |io|
35
- YAML.dump(@manifest, io)
24
+ YAML.dump(@@manifest, io)
36
25
  end
37
26
  end
38
27
 
@@ -64,22 +53,27 @@ module CFManifests
64
53
  def load_manifest(file)
65
54
  check_manifest! Loader.new(file, self).manifest
66
55
  end
67
-
68
- def check_manifest!(manifest_hash)
69
- manifest_hash[:applications].each{|app| check_attributes! app}
56
+
57
+ def check_manifest!(manifest_hash, output = $stdout)
58
+ manifest_hash[:applications].each{ |app| check_attributes!(app, output) }
70
59
  manifest_hash
71
60
  end
72
-
73
- def check_attributes!(app)
61
+
62
+ def check_attributes!(app, output = $stdout)
74
63
  app.each do |k, v|
75
- raise BadManifestError.new(k) unless known_manifest_attributes.include? k
76
- end
64
+ output.puts error_message_for_attribute(k) unless known_manifest_attributes.include? k
65
+ end
66
+ end
67
+
68
+ def error_message_for_attribute(attribute)
69
+ "\e[31mWarning: #{attribute} is not a valid manifest attribute. Please " +
70
+ "remove this attribute from your manifest to get rid of this warning\e[0m"
77
71
  end
78
72
 
79
73
  def known_manifest_attributes
80
- [:path, :name, :memory, :instances, :host, :domain,
81
- :command, :buildpack, :services, :env, :properties,
82
- :inherit, :mem, :disk, :runtime, :applications]
74
+ [:applications, :buildpack, :command, :disk, :domain, :env,
75
+ :host, :inherit, :instances, :mem, :memory, :name,
76
+ :path, :properties, :runtime, :services, :stack]
83
77
  end
84
78
 
85
79
  # dynamic symbol resolution
@@ -0,0 +1,25 @@
1
+ [![Build Status](https://travis-ci.org/cloudfoundry/micro-cf-plugin.png)](https://travis-ci.org/cloudfoundry/micro-cf-plugin)
2
+ [![Gem Version](https://badge.fury.io/rb/micro-cf-plugin.png)](http://badge.fury.io/rb/micro-cf-plugin)
3
+
4
+ ## Micro Cloud Foundry
5
+ ### Info
6
+ This plugin allows you to manage your Micro Cloud Foundry VM.
7
+
8
+ ### Installation
9
+
10
+ If you have installed CF via gem install, use:
11
+ ```
12
+ gem install micro-cf-plugin
13
+ ```
14
+
15
+ If you have installed CF through bundler and the Gemfile, add the following to your Gemfile:
16
+ ```
17
+ gem "micro-cf-plugin"
18
+ ```
19
+
20
+ ### Usage
21
+ ```
22
+ micro-status VMX [PASSWORD] Display Micro Cloud Foundry VM status
23
+ micro-offline VMX [PASSWORD] Micro Cloud Foundry offline mode
24
+ micro-online VMX [PASSWORD] Micro Cloud Foundry online mode
25
+ ```
@@ -0,0 +1,4 @@
1
+ module CFMicro
2
+ class MCFError < RuntimeError
3
+ end
4
+ end
@@ -0,0 +1,56 @@
1
+ require 'find'
2
+ require "micro/errors"
3
+
4
+ module CFMicro
5
+ def config_file(file)
6
+ File.expand_path("../../../../config/#{file}", __FILE__)
7
+ end
8
+
9
+ def escape_path(path)
10
+ path = File.expand_path(path)
11
+ if RUBY_PLATFORM =~ /mingw|mswin32|cygwin/
12
+ if path.include?(' ')
13
+ '"' + path + '"'
14
+ else
15
+ path
16
+ end
17
+ else
18
+ path.gsub(' ', '\ ')
19
+ end
20
+ end
21
+
22
+ def locate_file(file, directory, search_paths)
23
+ search_paths.each do |path|
24
+ expanded_path = File.expand_path(path)
25
+ next unless File.exists?(expanded_path)
26
+ Find.find(expanded_path) do |current|
27
+ if File.directory?(current) && current.include?(directory)
28
+ full_path = File.join(current, file)
29
+ return escape_path(full_path) if File.exists?(full_path)
30
+ end
31
+ end
32
+ end
33
+
34
+ false
35
+ end
36
+
37
+ def run_command(command, args=nil)
38
+ # TODO switch to using posix-spawn instead
39
+ result = %x{#{command} #{args} 2>&1}
40
+ if $?.exitstatus == 0
41
+ result.split(/\n/)
42
+ else
43
+ if block_given?
44
+ yield
45
+ else
46
+ raise CFMicro::MCFError, "failed to execute #{command} #{args}:\n#{result}"
47
+ end
48
+ end
49
+ end
50
+
51
+ module_function :config_file
52
+ module_function :escape_path
53
+ module_function :locate_file
54
+ module_function :run_command
55
+
56
+ end
@@ -0,0 +1,197 @@
1
+ require "yaml"
2
+ require "multi_json"
3
+ require "cf/cli"
4
+ require "micro/micro"
5
+ require "micro/vmrun"
6
+ require "micro/switcher/base"
7
+ require "micro/switcher/darwin"
8
+ require "micro/switcher/linux"
9
+ require "micro/switcher/windows"
10
+
11
+ module CFMicro
12
+ class McfCommand < CF::CLI
13
+ MICRO_FILE = '~/.cf/micro.yml'
14
+
15
+ desc "Display Micro Cloud Foundry VM status"
16
+ input :vmx, :argument => :required,
17
+ :desc => "Path to micro.vmx"
18
+ input :password, :argument => :optional,
19
+ :desc => "Cleartext password for guest VM vcap user"
20
+ def micro_status
21
+ mode = runner.offline? ? 'offline' : 'online'
22
+
23
+ line "Micro Cloud Foundry VM currently in #{b(mode)} mode"
24
+ line "VMX Path: #{c(runner.vmx, :good)}"
25
+ line "Domain: #{c(runner.domain, :good)}"
26
+ line "IP Address: #{c(runner.ip, :good)}"
27
+ end
28
+
29
+ desc "Micro Cloud Foundry offline mode"
30
+ input :vmx, :argument => :required,
31
+ :desc => "Path to micro.vmx"
32
+ input :password, :argument => :optional,
33
+ :desc => "Cleartext password for guest VM vcap user"
34
+ def micro_offline
35
+ if !runner.nat?
36
+ if ask("Reconfigure MCF VM network to nat mode and reboot?", :default => true)
37
+ with_progress("Rebooting MCF VM") do
38
+ runner.reset_to_nat!
39
+ end
40
+ else
41
+ fail "Aborted"
42
+ end
43
+ end
44
+
45
+ with_progress("Setting MCF VM to offline mode") do
46
+ runner.offline!
47
+ end
48
+
49
+ with_progress("Setting host DNS server") do
50
+ runner.set_host_dns!
51
+ end
52
+ end
53
+
54
+ desc "Micro Cloud Foundry online mode"
55
+ input :vmx, :argument => :required,
56
+ :desc => "Path to micro.vmx"
57
+ input :password, :argument => :optional,
58
+ :desc => "Cleartext password for guest VM vcap user"
59
+ def micro_online
60
+ runner
61
+ with_progress("Unsetting host DNS server") do
62
+ runner.unset_host_dns!
63
+ end
64
+
65
+ with_progress("Setting MCF VM to online mode") do
66
+ runner.online!
67
+ end
68
+ end
69
+
70
+ def runner
71
+ return @runner if @runner
72
+
73
+ config = build_config
74
+ @runner = switcher(config)
75
+ check_vm_running
76
+ store_config(config)
77
+
78
+ @runner
79
+ end
80
+
81
+ def check_vm_running
82
+ unless runner.running?
83
+ if ask("MCF VM is not running. Do you want to start it?", :default => true)
84
+ with_progress("Starting MCF VM") do
85
+ runner.start!
86
+ end
87
+ else
88
+ fail "MCF VM needs to be running."
89
+ end
90
+ end
91
+
92
+ unless runner.ready?
93
+ fail "MCF VM initial setup needs to be completed before using 'cf micro'"
94
+ end
95
+ end
96
+
97
+ def switcher(config)
98
+ case McfCommand.platform
99
+ when :darwin
100
+ CFMicro::Switcher::Darwin.new(config)
101
+ when :linux
102
+ CFMicro::Switcher::Linux.new(config)
103
+ when :windows
104
+ CFMicro::Switcher::Windows.new(config)
105
+ when :dummy # for testing only
106
+ CFMicro::Switcher::Dummy.new(config)
107
+ else
108
+ fail "unsupported platform: #{McfCommand.platform}"
109
+ end
110
+ end
111
+
112
+ # Returns the configuration needed to run the micro related subcommands.
113
+ # First loads saved config from file (if there is any), then overrides
114
+ # loaded values with command line arguments, and finally tries to guess
115
+ # in case neither was used:
116
+ # vmx location of micro.vmx file
117
+ # vmrun location of vmrun command
118
+ # password password for vcap user (in the guest vm)
119
+ # platform current platform
120
+ def build_config
121
+ conf = micro # returns {} if there isn't a saved config
122
+
123
+ override(conf, :vmx, true) do
124
+ locate_vmx(McfCommand.platform)
125
+ end
126
+
127
+ override(conf, :vmrun, true) do
128
+ CFMicro::VMrun.locate(McfCommand.platform)
129
+ end
130
+
131
+ override(conf, :password) do
132
+ ask("Please enter your MCF VM password (vcap user) password", :echo => "*")
133
+ end
134
+
135
+ conf[:platform] = McfCommand.platform
136
+
137
+ conf
138
+ end
139
+
140
+ # Save the cleartext password if --save is supplied.
141
+ # Note: it is due to vix we have to use a cleartext password :(
142
+ # Only if --password is used and not --save is the password deleted from the
143
+ # config file before it is stored to disk.
144
+ def store_config(config)
145
+ if input[:save]
146
+ warn("cleartext password saved in: #{MICRO_FILE}")
147
+ end
148
+
149
+ store_micro(config)
150
+ end
151
+
152
+ # override with command line arguments and yield the block in case the option isn't set
153
+ def override(config, option, escape=false, &blk)
154
+ # override if given on the command line
155
+ if opt = input[option]
156
+ opt = CFMicro.escape_path(opt) if escape
157
+ config[option] = opt
158
+ end
159
+ config[option] = yield unless config[option]
160
+ end
161
+
162
+ def locate_vmx(platform)
163
+ paths = YAML.load_file(CFMicro.config_file('paths.yml'))
164
+ vmx_paths = paths[platform.to_s]['vmx']
165
+ vmx = CFMicro.locate_file('micro.vmx', 'micro', vmx_paths)
166
+ fail "Unable to locate micro.vmx, please supply --vmx option" unless vmx
167
+ vmx
168
+ end
169
+
170
+ def self.platform
171
+ case RUBY_PLATFORM
172
+ when /darwin/ # x86_64-darwin11.2.0
173
+ :darwin
174
+ when /linux/ # x86_64-linux
175
+ :linux
176
+ when /mingw|mswin32|cygwin/ # i386-mingw32
177
+ :windows
178
+ else
179
+ RUBY_PLATFORM
180
+ end
181
+ end
182
+
183
+ def micro
184
+ micro_file = File.expand_path(MICRO_FILE)
185
+ return {} unless File.exists? micro_file
186
+ contents = File.read(micro_file).strip
187
+ MultiJson.load(contents)
188
+ end
189
+
190
+ def store_micro(micro)
191
+ micro_file = File.expand_path(MICRO_FILE)
192
+ File.open(micro_file, 'w') do |file|
193
+ file.write(MultiJson.dump(micro))
194
+ end
195
+ end
196
+ end
197
+ end