faastruby 0.4.18 → 0.5.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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -3
  3. data/Gemfile.lock +28 -4
  4. data/README.md +63 -5
  5. data/faastruby.gemspec +5 -1
  6. data/lib/faastruby.rb +1 -0
  7. data/lib/faastruby/api.rb +154 -6
  8. data/lib/faastruby/base.rb +3 -9
  9. data/lib/faastruby/cli.rb +39 -12
  10. data/lib/faastruby/cli/base_command.rb +66 -0
  11. data/lib/faastruby/cli/commands.rb +122 -59
  12. data/lib/faastruby/cli/commands/account/base_command.rb +10 -0
  13. data/lib/faastruby/cli/commands/account/confirm.rb +94 -0
  14. data/lib/faastruby/cli/commands/account/login.rb +86 -0
  15. data/lib/faastruby/cli/commands/account/logout.rb +59 -0
  16. data/lib/faastruby/cli/commands/account/signup.rb +76 -0
  17. data/lib/faastruby/cli/commands/{function.rb → function/base_command.rb} +2 -11
  18. data/lib/faastruby/cli/commands/function/build.rb +18 -11
  19. data/lib/faastruby/cli/commands/function/deploy_to.rb +100 -37
  20. data/lib/faastruby/cli/commands/function/new.rb +89 -36
  21. data/lib/faastruby/cli/commands/function/remove_from.rb +21 -6
  22. data/lib/faastruby/cli/commands/function/run.rb +15 -15
  23. data/lib/faastruby/cli/commands/function/test.rb +5 -4
  24. data/lib/faastruby/cli/commands/function/update_context.rb +10 -3
  25. data/lib/faastruby/cli/commands/function/upgrade.rb +62 -61
  26. data/lib/faastruby/cli/commands/help.rb +33 -20
  27. data/lib/faastruby/cli/commands/project/base_command.rb +14 -0
  28. data/lib/faastruby/cli/commands/project/deploy.rb +114 -0
  29. data/lib/faastruby/cli/commands/project/down.rb +58 -0
  30. data/lib/faastruby/cli/commands/project/new.rb +237 -0
  31. data/lib/faastruby/cli/commands/workspace/cp.rb +107 -0
  32. data/lib/faastruby/cli/commands/workspace/create.rb +35 -27
  33. data/lib/faastruby/cli/commands/workspace/destroy.rb +14 -7
  34. data/lib/faastruby/cli/commands/workspace/list.rb +15 -6
  35. data/lib/faastruby/cli/commands/workspace/migrate.rb +93 -0
  36. data/lib/faastruby/cli/commands/workspace/rm.rb +81 -0
  37. data/lib/faastruby/cli/commands/workspace/update.rb +62 -0
  38. data/lib/faastruby/cli/credentials.rb +58 -57
  39. data/lib/faastruby/cli/new_credentials.rb +63 -0
  40. data/lib/faastruby/cli/package.rb +1 -0
  41. data/lib/faastruby/cli/template.rb +7 -7
  42. data/lib/faastruby/local.rb +188 -0
  43. data/lib/faastruby/local/crystal_runtime.cr +170 -0
  44. data/lib/faastruby/local/functions.rb +7 -0
  45. data/lib/faastruby/local/functions/crystal.rb +64 -0
  46. data/lib/faastruby/local/functions/function.rb +173 -0
  47. data/lib/faastruby/local/functions/ruby.rb +28 -0
  48. data/lib/faastruby/local/listeners.rb +5 -0
  49. data/lib/faastruby/local/listeners/listener.rb +104 -0
  50. data/lib/faastruby/local/logger.rb +37 -0
  51. data/lib/faastruby/local/monkey_patch.rb +38 -0
  52. data/lib/faastruby/local/processors.rb +7 -0
  53. data/lib/faastruby/local/processors/function.rb +151 -0
  54. data/lib/faastruby/local/processors/processor.rb +116 -0
  55. data/lib/faastruby/local/processors/static_file.rb +48 -0
  56. data/lib/faastruby/local/static_files.rb +5 -0
  57. data/lib/faastruby/local/static_files/static_file.rb +59 -0
  58. data/lib/faastruby/server.rb +44 -3
  59. data/lib/faastruby/server/app.rb +107 -0
  60. data/lib/faastruby/server/concurrency_controller.rb +50 -50
  61. data/lib/faastruby/server/config.ru +2 -0
  62. data/lib/faastruby/server/event.rb +3 -0
  63. data/lib/faastruby/server/event_hub.rb +7 -6
  64. data/lib/faastruby/server/local.rb +22 -0
  65. data/lib/faastruby/server/logger.rb +50 -0
  66. data/lib/faastruby/server/project_config.rb +44 -0
  67. data/lib/faastruby/server/puma.rb +4 -0
  68. data/lib/faastruby/server/response.rb +40 -0
  69. data/lib/faastruby/server/runner.rb +116 -21
  70. data/lib/faastruby/server/runner_methods.rb +17 -16
  71. data/lib/faastruby/server/sentinel.rb +496 -0
  72. data/lib/faastruby/supported_runtimes.rb +8 -0
  73. data/lib/faastruby/user.rb +77 -0
  74. data/lib/faastruby/version.rb +1 -1
  75. data/lib/faastruby/workspace.rb +36 -3
  76. data/templates/crystal/example-blank/handler.cr +3 -0
  77. data/templates/crystal/example/spec/handler_spec.cr +11 -6
  78. data/templates/public-web/assets/images/background.png +0 -0
  79. data/templates/public-web/assets/images/ruby.png +0 -0
  80. data/templates/public-web/assets/javascripts/main.js +1 -0
  81. data/templates/public-web/assets/stylesheets/main.css +70 -0
  82. data/templates/public-web/favicon.ico +0 -0
  83. data/templates/ruby/api-404/handler.rb +6 -0
  84. data/templates/ruby/api-root/handler.rb +6 -0
  85. data/templates/ruby/example-blank/handler.rb +0 -23
  86. data/templates/ruby/web-404/404.html +36 -0
  87. data/templates/ruby/web-404/handler.rb +3 -0
  88. data/templates/ruby/web-root/handler.rb +10 -0
  89. data/templates/ruby/web-root/index.html.erb +37 -0
  90. data/templates/ruby/web-root/template.rb +13 -0
  91. metadata +102 -21
  92. data/exe/faastruby-server +0 -76
  93. data/lib/faastruby/cli/commands/credentials.rb +0 -11
  94. data/lib/faastruby/cli/commands/credentials/add.rb +0 -58
  95. data/lib/faastruby/cli/commands/credentials/list.rb +0 -58
  96. data/lib/faastruby/cli/commands/workspace.rb +0 -13
  97. data/lib/faastruby/cli/commands/workspace/deploy.rb +0 -50
  98. data/templates/crystal/example-blank/README.md +0 -22
  99. data/templates/crystal/example-blank/spec/handler_spec.cr +0 -8
  100. data/templates/crystal/example-blank/spec/spec_helper.cr +0 -4
  101. data/templates/crystal/example-blank/src/handler.cr +0 -25
  102. data/templates/ruby/example-blank/Gemfile +0 -7
  103. data/templates/ruby/example-blank/README.md +0 -22
  104. data/templates/ruby/example-blank/spec/handler_spec.rb +0 -16
  105. data/templates/ruby/example-blank/spec/spec_helper.rb +0 -3
@@ -0,0 +1,58 @@
1
+ require 'open3'
2
+ module FaaStRuby
3
+ module Command
4
+ STDOUT_MUTEX = Mutex.new
5
+ module Project
6
+ require 'faastruby/cli/commands/project/base_command'
7
+ require 'faastruby/server/logger'
8
+ class Down < ProjectBaseCommand
9
+ extend FaaStRuby::Logger
10
+ def initialize(args)
11
+ @args = args
12
+ help
13
+ parse_options
14
+ @options['environment'] ||= 'stage'
15
+ @project_yaml = YAML.load(File.read(PROJECT_YAML_FILE))['project'] rescue FaaStRuby::CLI.error("Could not find file 'project.yml'. Are you running this command from the project's folder?")
16
+ @project_name = @project_yaml['name']
17
+ @project_identifier = "-#{@project_yaml['identifier']}" if @project_yaml['identifier']
18
+ end
19
+
20
+ def run
21
+ workspace = "#{@project_name}-#{@options['environment']}#{@project_identifier}"
22
+ if @options['force']
23
+ exec("faastruby destroy-workspace #{workspace} -y")
24
+ else
25
+ exec("faastruby destroy-workspace #{workspace}")
26
+ end
27
+ end
28
+
29
+ def self.help
30
+ "down [ARGS]"
31
+ end
32
+
33
+ def usage
34
+ puts "Usage: faastruby #{self.class.help}"
35
+ puts %(
36
+ -e,--env ENVIRONMENT # ENVIRONMENT is added to the project name to compose the workspace name.
37
+ )
38
+ end
39
+
40
+ def parse_options
41
+ @options = {'functions' => []}
42
+ while @args.any?
43
+ option = @args.shift
44
+ case option
45
+ when '-y', '--yes'
46
+ @options['force'] = true
47
+ when '--env', '-e'
48
+ @options['environment'] = @args.shift
49
+ else
50
+ FaaStRuby::CLI.error("Unknown argument: #{option}")
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,237 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Project
4
+ require 'faastruby/cli/commands/project/base_command'
5
+ require 'faastruby/cli/template'
6
+ require 'faastruby/cli/commands/function/new'
7
+
8
+ DEFAULT_FUNCTIONS = {
9
+ 'root' => "local:#{FaaStRuby::Template.gem_template_path_for('web-root', runtime: 'ruby')}",
10
+ 'catch-all' => "local:#{FaaStRuby::Template.gem_template_path_for('web-404', runtime: 'ruby')}",
11
+ }
12
+ def self.templates_for(kind)
13
+ t = {
14
+ 'root' => "local:#{FaaStRuby::Template.gem_template_path_for("#{kind}-root", runtime: 'ruby')}",
15
+ 'catch-all' => "local:#{FaaStRuby::Template.gem_template_path_for("#{kind}-404", runtime: 'ruby')}"
16
+ }
17
+ return t
18
+ end
19
+ class New < ProjectBaseCommand
20
+ def initialize(args)
21
+ @args = args
22
+ help
23
+ @missing_args = []
24
+ FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
25
+ @project_name = @args.shift
26
+ FaaStRuby::CLI.error("The project name must have between 3 and 15 characters, and can only have letters, numbers and dashes.") unless name_valid?
27
+ @base_dir = "./#{@project_name}"
28
+ parse_options
29
+ @options['credentials_file'] ||= PROJECT_CREDENTIALS_FILE
30
+ @options['project_type'] ||= 'web'
31
+ end
32
+
33
+ def run
34
+ dir_exists?
35
+ create_dir
36
+ create_config
37
+ install_functions
38
+ git_init
39
+ puts "Project '#{@project_name}' initialized."
40
+ puts "Now run:"
41
+ puts "$ cd #{@project_name}"
42
+ puts "$ faastruby local\n\n"
43
+ puts "Then visit http://localhost:3000"
44
+ end
45
+
46
+ def self.help
47
+ "new-project PROJECT_NAME [ARGS]"
48
+ end
49
+
50
+ def usage
51
+ puts "Usage: faastruby #{self.class.help}"
52
+ puts %(
53
+ --api # Initialize a project folder using an API template
54
+ --web # (Default) Initialize a project folder using a WEB template
55
+ )
56
+ end
57
+
58
+ private
59
+
60
+ def create_dir
61
+ FileUtils.mkdir_p(@base_dir)
62
+ puts "+ d #{@base_dir}".green
63
+ end
64
+
65
+ def git_init
66
+ File.write("#{@base_dir}/.gitignore", "secrets.yml")
67
+ puts "+ f #{@base_dir}/.gitignore".green
68
+ puts `git init #{@base_dir}`
69
+ end
70
+
71
+ def install_functions
72
+ current_dir = Dir.pwd
73
+ FileUtils.mkdir_p("#{@base_dir}/functions")
74
+ Dir.chdir("#{@base_dir}/functions")
75
+ Project.templates_for(@options['project_type']).each do |name, template|
76
+ args = [name, '--template', template]
77
+ FaaStRuby::Command::Function::New.new(args).run(print_base_dir: "#{@base_dir}/functions", blank_template: true)
78
+ end
79
+ Dir.chdir("..")
80
+ if @options['project_type'] == 'web'
81
+ copy_public_template
82
+ else
83
+ create_public_folder
84
+ end
85
+ Dir.chdir(current_dir)
86
+ end
87
+
88
+ def create_public_folder
89
+ Dir.mkdir 'public'
90
+ puts "+ d #{@base_dir}/public".green
91
+ write_public_config
92
+ end
93
+
94
+ def copy_public_template
95
+ template_dir = "#{Gem::Specification.find_by_name("faastruby").gem_dir}/templates/public-#{@options['project_type']}"
96
+ FileUtils.cp_r(template_dir, "./public")
97
+ write_public_config
98
+ end
99
+
100
+ def write_public_config
101
+ File.write("public/faastruby.yml", default_public_config)
102
+ puts "+ f #{@base_dir}/public/faastruby.yml".green
103
+ end
104
+
105
+ def create_config
106
+ File.write("#{@base_dir}/#{PROJECT_YAML_FILE}", default_project_file)
107
+ puts "+ f #{@base_dir}/#{PROJECT_YAML_FILE}".green
108
+ if @options['tmux']
109
+ File.write("#{@base_dir}/tmuxinator.yml", tmuxinator_config)
110
+ puts "+ f #{@base_dir}/tmuxinator.yml".green
111
+ end
112
+ File.write("#{@base_dir}/#{PROJECT_SECRETS_FILE}", default_secrets_file)
113
+ puts "+ f #{@base_dir}/#{PROJECT_SECRETS_FILE}".green
114
+ end
115
+
116
+ def default_public_config
117
+ [
118
+ "cli_version: #{FaaStRuby::VERSION}",
119
+ 'name: public',
120
+ 'serve_static: true',
121
+ ].join("\n")
122
+ end
123
+
124
+ def default_secrets_file
125
+ [
126
+ 'secrets:',
127
+ " # Add secrets here and they will be available inside the function as \"event.context\"",
128
+ " # Example:",
129
+ " # prod:",
130
+ " # pages/root:",
131
+ " # a_secret: bfe76f4557ffc2de901cb24e0f87436f",
132
+ " # another/function:",
133
+ " # another_secret: 4d1c281e.619a2489c.8b5d.dd945616d324",
134
+ " # stage:",
135
+ " # pages/root:",
136
+ " # a_secret: bfe76f4557ffc2de901cb24e0f87436f",
137
+ " # another/function:",
138
+ " # another_secret: 4d1c281e.619a2489c.8b5d.dd945616d324"
139
+ ].join("\n")
140
+ end
141
+
142
+ def default_project_file
143
+ [
144
+ "project:",
145
+ " # The project name",
146
+ " name: #{@project_name}",
147
+ " # The project identifier is used to ensure your workspaces will have unique names.",
148
+ " # This is not a secret, but don't lose it!",
149
+ " identifier: #{Digest::MD5.hexdigest(Time.now.to_s).slice(0..5)}",
150
+ "",
151
+ " ## The 'public' directory, where you put static files.",
152
+ " ## Files will be served from here first, meaning that if",
153
+ " ## you have a function at '/product' and a folder '/product'",
154
+ " ## inside the public folder, the public one will take precedence.",
155
+ " ## Defaults to 'public'.",
156
+ " # public_dir: public",
157
+ "",
158
+ " ## The name of the folder containing your functions. Defaults to 'functions'",
159
+ " # functions_dir: functions",
160
+ "",
161
+ " ## The name of the function that will respond to requests made",
162
+ " ## to '/'. Defaults to 'root'",
163
+ " # root_to: root",
164
+ "",
165
+ " ## The setting 'catch_all' allows you to capture requests to",
166
+ " ## non-existing functions and send them to another function.",
167
+ " ## This is useful for setting custom 404 pages, for example.",
168
+ " ## Defaults to 'catch-all'.",
169
+ " # catch_all: catch-all"
170
+ ].join("\n")
171
+ end
172
+
173
+ def tmuxinator_config
174
+ {
175
+ "name" => @project_name,
176
+ "root" => ".",
177
+ "startup_window" => "server",
178
+ "windows" => [{
179
+ "server" => {
180
+ "layout" => "main-horizontal",
181
+ "panes" => [
182
+ [
183
+ "tmux set -g mouse on",
184
+ "tmux set -g history-limit 30000",
185
+ "clear",
186
+ "faastruby server"
187
+ ],
188
+ [
189
+ "tmux select-pane -t 0.1",
190
+ "clear"
191
+ ]
192
+ ]
193
+ }
194
+ }
195
+ ]
196
+ }.to_yaml
197
+ end
198
+
199
+ def dir_exists?
200
+ return false unless File.directory?(@base_dir)
201
+ FaaStRuby::CLI.error("Error: Directory '#{@project_name}' already exists. Aborting.")
202
+ end
203
+
204
+ def name_valid?
205
+ return true if @project_name.match(/^#{WORKSPACE_NAME_REGEX}$/)
206
+ return false
207
+ end
208
+
209
+ def missing_args
210
+ if @args.empty?
211
+ @missing_args << "Missing argument: PROJECT_NAME".red
212
+ @missing_args << usage
213
+ end
214
+ FaaStRuby::CLI.error(["'#{@args.first}' is not a valid project name.".red, usage], color: nil) if @args.first =~ /^-.*/
215
+ @missing_args
216
+ end
217
+
218
+ def parse_options
219
+ @options = {}
220
+ while @args.any?
221
+ option = @args.shift
222
+ case option
223
+ when '--tmux'
224
+ @options['tmux'] = true
225
+ when '--web', '-w'
226
+ @options['project_type'] = 'web'
227
+ when '--api', '-a'
228
+ @options['project_type'] = 'api'
229
+ else
230
+ FaaStRuby::CLI.error("Unknown argument: #{option}")
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,107 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Workspace
4
+ require 'tmpdir'
5
+ require 'tempfile'
6
+ # require 'faastruby/cli/commands/workspace/base_command'
7
+ require 'faastruby/cli/package'
8
+ require 'faastruby/cli/new_credentials'
9
+ class CP < BaseCommand
10
+ def initialize(args)
11
+ @args = args
12
+ help
13
+ @source_file = @args.shift
14
+ @workspace_name, @relative_path = @args.shift.split(':')
15
+ validate_command
16
+ @package_file = Tempfile.new('package')
17
+ @tmpdir = Dir.mktmpdir("package")
18
+ # FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
19
+ load_credentials
20
+ end
21
+
22
+ def run
23
+ destination_url = "#{FaaStRuby.workspace_host_for(@workspace_name)}/#{@relative_path}"
24
+ spinner = say("[#{@source_file}] Copying file to '#{destination_url}'...", quiet: true)
25
+ workspace = FaaStRuby::Workspace.new(name: @workspace_name)
26
+ package = build_package
27
+ workspace.upload_file(package, relative_path: @relative_path)
28
+ FaaStRuby::CLI.error(workspace.errors) if workspace.errors.any?
29
+ # spinner.stop("Done!")
30
+ puts "* [#{@source_file}] Upload OK".green
31
+ puts "* [#{@source_file}] URL: #{destination_url}".green
32
+ ensure
33
+ FileUtils.remove_entry @tmpdir
34
+ @package_file.unlink
35
+ end
36
+
37
+
38
+ def build_package
39
+ FileUtils.cp @source_file, @tmpdir
40
+ output_file = @package_file.path
41
+ FaaStRuby::Package.new(@tmpdir, output_file).build
42
+ # FaaStRuby::Command::Function::Build.build(@source_file, output_file, @function_name, true)
43
+ @package_file.close
44
+ output_file
45
+ end
46
+
47
+ def self.help
48
+ "cp SOURCE_FILE WORKSPACE_NAME:/DESTINATION/PATH"
49
+ end
50
+
51
+ def usage
52
+ puts "\n# Deploy static file SOURCE_FILE to workspace path /DESTINATION/PATH.\n"
53
+ puts "\nUsage: faastruby #{self.class.help}\n\n"
54
+ end
55
+
56
+ private
57
+
58
+ def validate_command
59
+ validate_source_file
60
+ validate_workspace_name
61
+ validate_relative_path
62
+ end
63
+
64
+ def validate_relative_path
65
+ @relative_path.sub!(/^\//, '')
66
+ FaaStRuby::CLI.error(["Invalid destination path: #{@relative_path}".red, "The destination path must have at least one character and can only contain letters, numbers, -, _, . and /."], color: nil) unless @relative_path&.match(/#{FUNCTION_NAME_REGEX}/)
67
+ end
68
+
69
+ def validate_workspace_name
70
+ FaaStRuby::CLI.error(["Invalid workspace name: #{@workspace_name}".red, "The workspace name must have between 3 and 15 characters, and can only have letters, numbers and dashes."], color: nil) unless @workspace_name&.match(/#{WORKSPACE_NAME_REGEX}/)
71
+ true
72
+ end
73
+
74
+ def validate_source_file
75
+ FaaStRuby::CLI.error(["You must specify source file, workspace and destination path for the file.".red, usage], color: nil) unless (@source_file && @source_file != '')
76
+ FaaStRuby::CLI.error("No such file: '#{@source_file}'") unless File.exists?(@source_file)
77
+ FaaStRuby::CLI.error("You can only 'cp' files, not directories.") unless File.file?(@source_file)
78
+ true
79
+ end
80
+
81
+ # def missing_args
82
+ # FaaStRuby::CLI.error(["'#{@workspace_name}' is not a valid workspace name.".red, usage], color: nil) if @workspace_name =~ /^-.*/
83
+ # @missing_args << "Missing argument: WORKSPACE_NAME".red unless @workspace_name
84
+ # @missing_args << "Missing argument: -s SOURCE_FILE" unless @options['source']
85
+ # @missing_args << "Missing argument: -d DESTINATION_PATH" unless @options['destination']
86
+ # @missing_args << usage if @missing_args.any?
87
+ # @missing_args
88
+ # end
89
+
90
+ # def parse_options(require_options: {})
91
+ # @options = {}
92
+ # while @args.any?
93
+ # option = @args.shift
94
+ # case option
95
+ # when '-s', '--source'
96
+ # @options['source'] = @args.shift
97
+ # when '-d', '--destination'
98
+ # @options['destination'] = @args.shift.gsub(/(^\/|\/$|\.\.|;|'|"|&|\\)/, '')
99
+ # else
100
+ # FaaStRuby::CLI.error("Unknown argument: #{option}")
101
+ # end
102
+ # end
103
+ # end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -1,40 +1,47 @@
1
1
  module FaaStRuby
2
2
  module Command
3
3
  module Workspace
4
- class Create < WorkspaceBaseCommand
4
+ # require 'faastruby/cli/commands/workspace/base_command'
5
+ require 'faastruby/cli/new_credentials'
6
+ class Create < BaseCommand
5
7
  def initialize(args)
6
8
  @args = args
9
+ help
7
10
  @missing_args = []
8
11
  FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
9
12
  @workspace_name = @args.shift
13
+ validate_name
10
14
  @base_dir = "./#{@workspace_name}"
11
15
  parse_options
12
- @options['credentials_file'] ||= FaaStRuby.credentials_file
16
+ load_credentials
13
17
  end
14
18
 
15
19
  def run(create_directory: true, exit_on_error: true)
16
- spinner = spin("Requesting credentials...")
17
- workspace = FaaStRuby::Workspace.create(name: @workspace_name, email: @options['email'])
18
- spinner.stop("Done!")
19
- FaaStRuby::CLI.error(workspace.errors) if workspace.errors.any? && exit_on_error
20
- if @options['stdout']
21
- puts "IMPORTANT: Please store the credentials below in a safe place. If you lose them you will not be able to manage your workspace.".yellow
22
- puts "API_KEY: #{workspace.credentials['api_key']}"
23
- puts "API_SECRET: #{workspace.credentials['api_secret']}"
24
- else
25
- puts "Writing credentials to #{@options['credentials_file']}"
26
- FaaStRuby::Credentials.add(@workspace_name, workspace.credentials, @options['credentials_file'])
20
+ unless @options['skip_creation']
21
+ spinner = spin("Setting up workspace '#{@workspace_name}'...")
22
+ workspace = FaaStRuby::Workspace.create(name: @workspace_name, email: @options['email'])
23
+ if workspace.errors.any?
24
+ spinner.stop(" Failed :(") if exit_on_error
25
+ FaaStRuby::CLI.error(workspace.errors) if exit_on_error
26
+ spinner.stop
27
+ return false
28
+ end
29
+ spinner.stop(" Done!")
27
30
  end
28
- puts "Workspace '#{@workspace_name}' created"
29
31
  create_dir if @options['create_local_dir'] && create_directory && !dir_exists?
32
+ true
30
33
  end
31
34
 
32
35
  def self.help
33
- "create-workspace".light_cyan + " WORKSPACE_NAME [--create-local-dir] [--stdout] [-c, --credentials-file CREDENTIALS_FILE] [-e, --email YOUR_EMAIL_ADDRESS]"
36
+ "create-workspace WORKSPACE_NAME [ARGS]"
34
37
  end
35
38
 
36
39
  def usage
37
- "Usage: faastruby #{self.class.help}"
40
+ puts "\nUsage: faastruby #{self.class.help}"
41
+ puts %(
42
+ --create-local-dir # Create a local folder in addition to the cloud
43
+ --local-only # Only create a local folder. Skip creating workspace on the cloud
44
+ )
38
45
  end
39
46
 
40
47
  private
@@ -46,7 +53,7 @@ module FaaStRuby
46
53
 
47
54
  def dir_exists?
48
55
  return false unless File.directory?(@base_dir)
49
- puts "Local folder '#{@workspace_name}' already exists."
56
+ puts "Error: Local folder '#{@workspace_name}' already exists.".red
50
57
  true
51
58
  end
52
59
 
@@ -59,23 +66,24 @@ module FaaStRuby
59
66
  @missing_args
60
67
  end
61
68
 
69
+ def validate_name
70
+ unless @workspace_name.match(/^#{WORKSPACE_NAME_REGEX}$/)
71
+ FaaStRuby::CLI.error("The workspace name must have between 3 and 15 characters, and can only have letters, numbers and dashes.")
72
+ end
73
+ end
74
+
62
75
  def parse_options
63
76
  @options = {}
64
77
  while @args.any?
65
78
  option = @args.shift
66
79
  case option
67
- # when '--file'
68
- # @options['credentials_file'] = @args.shift
69
- when '--stdout'
70
- @options['stdout'] = true
71
- when '--create-local-dir'
80
+ when '--create-local-dir',
81
+ @options['create_local_dir'] = true
82
+ when '--local-only'
72
83
  @options['create_local_dir'] = true
73
- when '-c', '--credentials-file'
74
- @options['credentials_file'] = @args.shift
75
- when '-e', '--email'
76
- @options['email'] = @args.shift
84
+ @options['skip_creation'] = true
77
85
  else
78
- FaaStRuby.error("Unknown argument: #{option}")
86
+ FaaStRuby::CLI.error("Unknown argument: #{option}")
79
87
  end
80
88
  end
81
89
  end