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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -3
- data/Gemfile.lock +28 -4
- data/README.md +63 -5
- data/faastruby.gemspec +5 -1
- data/lib/faastruby.rb +1 -0
- data/lib/faastruby/api.rb +154 -6
- data/lib/faastruby/base.rb +3 -9
- data/lib/faastruby/cli.rb +39 -12
- data/lib/faastruby/cli/base_command.rb +66 -0
- data/lib/faastruby/cli/commands.rb +122 -59
- data/lib/faastruby/cli/commands/account/base_command.rb +10 -0
- data/lib/faastruby/cli/commands/account/confirm.rb +94 -0
- data/lib/faastruby/cli/commands/account/login.rb +86 -0
- data/lib/faastruby/cli/commands/account/logout.rb +59 -0
- data/lib/faastruby/cli/commands/account/signup.rb +76 -0
- data/lib/faastruby/cli/commands/{function.rb → function/base_command.rb} +2 -11
- data/lib/faastruby/cli/commands/function/build.rb +18 -11
- data/lib/faastruby/cli/commands/function/deploy_to.rb +100 -37
- data/lib/faastruby/cli/commands/function/new.rb +89 -36
- data/lib/faastruby/cli/commands/function/remove_from.rb +21 -6
- data/lib/faastruby/cli/commands/function/run.rb +15 -15
- data/lib/faastruby/cli/commands/function/test.rb +5 -4
- data/lib/faastruby/cli/commands/function/update_context.rb +10 -3
- data/lib/faastruby/cli/commands/function/upgrade.rb +62 -61
- data/lib/faastruby/cli/commands/help.rb +33 -20
- data/lib/faastruby/cli/commands/project/base_command.rb +14 -0
- data/lib/faastruby/cli/commands/project/deploy.rb +114 -0
- data/lib/faastruby/cli/commands/project/down.rb +58 -0
- data/lib/faastruby/cli/commands/project/new.rb +237 -0
- data/lib/faastruby/cli/commands/workspace/cp.rb +107 -0
- data/lib/faastruby/cli/commands/workspace/create.rb +35 -27
- data/lib/faastruby/cli/commands/workspace/destroy.rb +14 -7
- data/lib/faastruby/cli/commands/workspace/list.rb +15 -6
- data/lib/faastruby/cli/commands/workspace/migrate.rb +93 -0
- data/lib/faastruby/cli/commands/workspace/rm.rb +81 -0
- data/lib/faastruby/cli/commands/workspace/update.rb +62 -0
- data/lib/faastruby/cli/credentials.rb +58 -57
- data/lib/faastruby/cli/new_credentials.rb +63 -0
- data/lib/faastruby/cli/package.rb +1 -0
- data/lib/faastruby/cli/template.rb +7 -7
- data/lib/faastruby/local.rb +188 -0
- data/lib/faastruby/local/crystal_runtime.cr +170 -0
- data/lib/faastruby/local/functions.rb +7 -0
- data/lib/faastruby/local/functions/crystal.rb +64 -0
- data/lib/faastruby/local/functions/function.rb +173 -0
- data/lib/faastruby/local/functions/ruby.rb +28 -0
- data/lib/faastruby/local/listeners.rb +5 -0
- data/lib/faastruby/local/listeners/listener.rb +104 -0
- data/lib/faastruby/local/logger.rb +37 -0
- data/lib/faastruby/local/monkey_patch.rb +38 -0
- data/lib/faastruby/local/processors.rb +7 -0
- data/lib/faastruby/local/processors/function.rb +151 -0
- data/lib/faastruby/local/processors/processor.rb +116 -0
- data/lib/faastruby/local/processors/static_file.rb +48 -0
- data/lib/faastruby/local/static_files.rb +5 -0
- data/lib/faastruby/local/static_files/static_file.rb +59 -0
- data/lib/faastruby/server.rb +44 -3
- data/lib/faastruby/server/app.rb +107 -0
- data/lib/faastruby/server/concurrency_controller.rb +50 -50
- data/lib/faastruby/server/config.ru +2 -0
- data/lib/faastruby/server/event.rb +3 -0
- data/lib/faastruby/server/event_hub.rb +7 -6
- data/lib/faastruby/server/local.rb +22 -0
- data/lib/faastruby/server/logger.rb +50 -0
- data/lib/faastruby/server/project_config.rb +44 -0
- data/lib/faastruby/server/puma.rb +4 -0
- data/lib/faastruby/server/response.rb +40 -0
- data/lib/faastruby/server/runner.rb +116 -21
- data/lib/faastruby/server/runner_methods.rb +17 -16
- data/lib/faastruby/server/sentinel.rb +496 -0
- data/lib/faastruby/supported_runtimes.rb +8 -0
- data/lib/faastruby/user.rb +77 -0
- data/lib/faastruby/version.rb +1 -1
- data/lib/faastruby/workspace.rb +36 -3
- data/templates/crystal/example-blank/handler.cr +3 -0
- data/templates/crystal/example/spec/handler_spec.cr +11 -6
- data/templates/public-web/assets/images/background.png +0 -0
- data/templates/public-web/assets/images/ruby.png +0 -0
- data/templates/public-web/assets/javascripts/main.js +1 -0
- data/templates/public-web/assets/stylesheets/main.css +70 -0
- data/templates/public-web/favicon.ico +0 -0
- data/templates/ruby/api-404/handler.rb +6 -0
- data/templates/ruby/api-root/handler.rb +6 -0
- data/templates/ruby/example-blank/handler.rb +0 -23
- data/templates/ruby/web-404/404.html +36 -0
- data/templates/ruby/web-404/handler.rb +3 -0
- data/templates/ruby/web-root/handler.rb +10 -0
- data/templates/ruby/web-root/index.html.erb +37 -0
- data/templates/ruby/web-root/template.rb +13 -0
- metadata +102 -21
- data/exe/faastruby-server +0 -76
- data/lib/faastruby/cli/commands/credentials.rb +0 -11
- data/lib/faastruby/cli/commands/credentials/add.rb +0 -58
- data/lib/faastruby/cli/commands/credentials/list.rb +0 -58
- data/lib/faastruby/cli/commands/workspace.rb +0 -13
- data/lib/faastruby/cli/commands/workspace/deploy.rb +0 -50
- data/templates/crystal/example-blank/README.md +0 -22
- data/templates/crystal/example-blank/spec/handler_spec.cr +0 -8
- data/templates/crystal/example-blank/spec/spec_helper.cr +0 -4
- data/templates/crystal/example-blank/src/handler.cr +0 -25
- data/templates/ruby/example-blank/Gemfile +0 -7
- data/templates/ruby/example-blank/README.md +0 -22
- data/templates/ruby/example-blank/spec/handler_spec.rb +0 -16
- 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
|
-
|
|
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
|
-
|
|
16
|
+
load_credentials
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def run(create_directory: true, exit_on_error: true)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
|
36
|
+
"create-workspace WORKSPACE_NAME [ARGS]"
|
|
34
37
|
end
|
|
35
38
|
|
|
36
39
|
def usage
|
|
37
|
-
"
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
when '--
|
|
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
|
-
|
|
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
|