faastruby 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Gemfile +6 -0
  5. data/Gemfile.lock +67 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +39 -0
  8. data/Rakefile +2 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +8 -0
  11. data/example-blank/Gemfile +5 -0
  12. data/example-blank/handler.rb +4 -0
  13. data/example-blank/spec/handler_spec.rb +11 -0
  14. data/example-blank/spec/helpers/faastruby.rb +23 -0
  15. data/example-blank/spec/spec_helper.rb +2 -0
  16. data/example/Gemfile +5 -0
  17. data/example/handler.rb +17 -0
  18. data/example/spec/handler_spec.rb +20 -0
  19. data/example/spec/helpers/faastruby.rb +23 -0
  20. data/example/spec/spec_helper.rb +2 -0
  21. data/exe/faastruby +5 -0
  22. data/faastruby.gemspec +41 -0
  23. data/lib/faastruby.rb +6 -0
  24. data/lib/faastruby/api.rb +94 -0
  25. data/lib/faastruby/base.rb +53 -0
  26. data/lib/faastruby/cli.rb +42 -0
  27. data/lib/faastruby/cli/commands.rb +61 -0
  28. data/lib/faastruby/cli/commands/function.rb +31 -0
  29. data/lib/faastruby/cli/commands/function/build.rb +65 -0
  30. data/lib/faastruby/cli/commands/function/deploy.rb +62 -0
  31. data/lib/faastruby/cli/commands/function/new.rb +99 -0
  32. data/lib/faastruby/cli/commands/function/remove_from.rb +71 -0
  33. data/lib/faastruby/cli/commands/function/run.rb +135 -0
  34. data/lib/faastruby/cli/commands/function/test.rb +42 -0
  35. data/lib/faastruby/cli/commands/function/update_context.rb +67 -0
  36. data/lib/faastruby/cli/commands/function/upgrade.rb +69 -0
  37. data/lib/faastruby/cli/commands/help.rb +31 -0
  38. data/lib/faastruby/cli/commands/version.rb +13 -0
  39. data/lib/faastruby/cli/commands/workspace.rb +12 -0
  40. data/lib/faastruby/cli/commands/workspace/create.rb +70 -0
  41. data/lib/faastruby/cli/commands/workspace/destroy.rb +66 -0
  42. data/lib/faastruby/cli/commands/workspace/list.rb +54 -0
  43. data/lib/faastruby/cli/credentials.rb +49 -0
  44. data/lib/faastruby/cli/package.rb +46 -0
  45. data/lib/faastruby/function.rb +27 -0
  46. data/lib/faastruby/version.rb +3 -0
  47. data/lib/faastruby/workspace.rb +49 -0
  48. metadata +203 -0
@@ -0,0 +1,135 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Function
4
+ class Run < FunctionBaseCommand
5
+ def initialize(args)
6
+ @args = args
7
+ @missing_args = []
8
+ FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
9
+ @options = {}
10
+ @options['workspace_name'] = @args.shift
11
+ load_yaml
12
+ @function_name = @yaml_config['name']
13
+ parse_options
14
+ @options['query'] = "?#{@options['query'].join('&')}" if @options['query']&.any?
15
+ end
16
+
17
+ def run
18
+ return curl if @options['curl']
19
+ function = FaaStRuby::Function.new(name: @function_name)
20
+ response = function.run(@options)
21
+ puts response.body
22
+ end
23
+
24
+ def curl
25
+ command = ["curl"]
26
+ command << "-X #{@options['method'].upcase}" if @options['method']
27
+ @options['headers']&.each {|h,v| command << "-H '#{h}: #{v}'"}
28
+ command << "-d '#{@options['body']}'" if @options['body']
29
+ command << "'#{HOST}/#{@options['workspace_name']}/#{@function_name}#{@options['query']}'"
30
+ puts command.join(" ")
31
+ end
32
+
33
+ def self.help
34
+ 'run'.blue + ' WORKSPACE_NAME [OPTIONS]' +
35
+ <<-EOS
36
+
37
+ Options:
38
+ -b, --body 'DATA' # The request body
39
+ --stdin # Read the request body from STDIN
40
+ -m, --method METHOD # The request method
41
+ -h, --header 'Header: Value' # Set a header. Can be used multiple times.
42
+ -f, --form 'a=1&b=2' # Send form data and set header 'Content-Type: application/x-www-form-urlencoded'
43
+ -j, --json '{"a":"1"}' # Send JSON data and set header 'Content-Type: application/json'
44
+ -t, --time # Return function run time in the response
45
+ -q, --query 'foo=bar' # Set a query parameter for the request. Can be used multiple times.
46
+ --curl # Return the CURL command equivalent for the request
47
+ EOS
48
+ end
49
+
50
+ def usage
51
+ "Usage: faastruby #{self.class.help}"
52
+ end
53
+
54
+ private
55
+
56
+ def parse_options
57
+ while @args.any?
58
+ option = @args.shift
59
+ case option
60
+ when '-b', '--body'
61
+ set_body
62
+ when '-j', '--json'
63
+ set_json
64
+ when '-f', '--form'
65
+ set_form
66
+ when '--stdin'
67
+ set_stdin
68
+ when '-m', '--method'
69
+ @options['method'] = @args.shift.downcase
70
+ when '-h', '--header'
71
+ set_header
72
+ when '-t', '--time'
73
+ @options['time'] = true
74
+ when '--curl'
75
+ @options['curl'] = true
76
+ when '-q', '--query'
77
+ set_query
78
+ else
79
+ FaaStRuby::CLI.error(["Unknown argument: #{option}".red, usage], color: nil)
80
+ end
81
+ end
82
+ end
83
+
84
+ def set_body
85
+ @options['method'] ||= 'post'
86
+ @options['body'] = @args.shift
87
+ default_content_type = 'text/plain'
88
+ @options['headers'] ? @options['headers']['Content-Type'] = default_content_type : @options['headers'] = {'Content-Type' => default_content_type}
89
+ end
90
+
91
+ def set_json
92
+ content_type = 'application/json'
93
+ @options['method'] ||= 'post'
94
+ @options['body'] = @args.shift
95
+ @options['headers'] ? @options['headers']['Content-Type'] = content_type : @options['headers'] = {'Content-Type' => content_type}
96
+ end
97
+
98
+ def set_form
99
+ content_type = 'application/x-www-form-urlencoded'
100
+ @options['method'] ||= 'post'
101
+ @options['body'] = @args.shift
102
+ @options['headers'] ? @options['headers']['Content-Type'] = content_type : @options['headers'] = {'Content-Type' => content_type}
103
+ end
104
+
105
+ def set_stdin
106
+ @options['method'] ||= 'post'
107
+ @options['body'] = STDIN.gets.chomp
108
+ content_type = 'text/plain'
109
+ @options['headers'] ? @options['headers']['Content-Type'] = content_type : @options['headers'] = {'Content-Type' => content_type}
110
+ end
111
+
112
+ def set_query
113
+ query = "#{@args.shift}"
114
+ @options['query'] ? @options['query'] << query : @options['query'] = [query]
115
+ end
116
+
117
+ def set_header
118
+ header = @args.shift
119
+ key, value = header.split(":")
120
+ value.strip!
121
+ @options['headers'] ? @options['headers'][key] = value : @options['headers'] = {key => value}
122
+ end
123
+
124
+ def missing_args
125
+ if @args.empty?
126
+ @missing_args << "Missing argument: WORKSPACE_NAME".red
127
+ @missing_args << usage
128
+ end
129
+ FaaStRuby::CLI.error(["'#{@args.first}' is not a valid workspace name.".red, usage], color: nil) if @args.first =~ /^-.*/
130
+ @missing_args
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,42 @@
1
+ require 'open3'
2
+ module FaaStRuby
3
+ module Command
4
+ module Function
5
+ class Test < FunctionBaseCommand
6
+ def initialize(args)
7
+ @args = args
8
+ load_yaml
9
+ @function_name = @yaml_config['name']
10
+ @test_command = @yaml_config['test_command']
11
+ end
12
+
13
+ def run(do_not_exit: false)
14
+ unless @test_command
15
+ puts "[skipped] You have no 'test_command' key/value in 'faastruby.yml'. Please consider using rspec!".yellow
16
+ return true
17
+ end
18
+ spinner = spin("Running tests...")
19
+ output, status = Open3.capture2e(@test_command)
20
+ if status == 0
21
+ spinner.stop('Passed!')
22
+ puts output
23
+ return true
24
+ else
25
+ spinner.stop('Failed :(')
26
+ FaaStRuby::CLI.error(output, color: nil) unless do_not_exit
27
+ puts output if do_not_exit
28
+ return false
29
+ end
30
+ end
31
+
32
+ def self.help
33
+ 'test'.blue
34
+ end
35
+
36
+ def usage
37
+ "Usage: faastruby #{self.class.help}"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,67 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Function
4
+ class UpdateContext < FunctionBaseCommand
5
+ def initialize(args)
6
+ @args = args
7
+ @missing_args = []
8
+ FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
9
+ @workspace_name = @args.shift
10
+ load_yaml
11
+ @function_name = @yaml_config['name']
12
+ FaaStRuby::Credentials.load_for(@workspace_name)
13
+ parse_options(require_options: {'data' => 'context data'} )
14
+ end
15
+
16
+ def run
17
+ spinner = spin("Uploading context data to '#{@workspace_name}'...")
18
+ workspace = FaaStRuby::Workspace.new(name: @workspace_name)
19
+ function = FaaStRuby::Function.new(name: @function_name, workspace: workspace, context: @options['data'])
20
+ function.update
21
+ if function.errors.any?
22
+ spinner.stop('Failed :(')
23
+ FaaStRuby::CLI.error(function.errors)
24
+ end
25
+ spinner.stop('Done!')
26
+ end
27
+
28
+ def self.help
29
+ "update-context".blue + " WORKSPACE_NAME [-d, --data 'STRING'] [--stdin]"
30
+ end
31
+
32
+ def usage
33
+ "Usage: faastruby #{self.class.help}"
34
+ end
35
+
36
+ private
37
+
38
+ def missing_args
39
+ if @args.empty?
40
+ @missing_args << "Missing argument: WORKSPACE_NAME".red
41
+ @missing_args << usage
42
+ end
43
+ FaaStRuby::CLI.error(["'#{@args.first}' is not a valid workspace name.".red, usage], color: nil) if @args.first =~ /^-.*/
44
+ @missing_args
45
+ end
46
+
47
+ def parse_options(require_options: {})
48
+ @options = {}
49
+ while @args.any?
50
+ option = @args.shift
51
+ case option
52
+ when '-d', '--data'
53
+ @options['data'] = @args.shift
54
+ when '--stdin'
55
+ @options['data'] = STDIN.gets.chomp
56
+ else
57
+ FaaStRuby::CLI.error("Unknown argument: #{option}")
58
+ end
59
+ end
60
+ require_options.keys.each do |option|
61
+ FaaStRuby::CLI.error(["Missing #{require_options[option]}".red, usage], color: nil) unless @options[option]
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,69 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Function
4
+ class Upgrade < FunctionBaseCommand
5
+ def initialize(args)
6
+ @args = args
7
+ end
8
+
9
+ def run
10
+ check_function_name
11
+ set_yaml_content
12
+ write_yaml
13
+ write_gemfile
14
+ copy_spec_folder
15
+ puts "Upgrade complete. Please read the documentation at https://faastruby.io/tutorial.html to learn about the changes."
16
+ puts "To deploy, run 'faastruby deploy-to WORKSPACE_NAME'."
17
+ end
18
+
19
+ def set_yaml_content
20
+ @yaml_content = {
21
+ 'name' => @function_name,
22
+ 'test_command' => nil,
23
+ 'abort_build_when_tests_fail' => false,
24
+ 'abort_deploy_when_tests_fail' => false
25
+ }
26
+ end
27
+
28
+ def check_function_name
29
+ FaaStRuby::CLI.error('You need to run this command from the function directory') unless File.file?('handler.rb')
30
+ @function_name = Dir.pwd.split('/').last
31
+ unless @function_name
32
+ puts "What's the name of this function? (accepts only letters, numbers, - or _)"
33
+ print "Enter function name: "
34
+ @function_name = STDIN.gets.chomp
35
+ end
36
+ FaaStRuby::CLI.error('You need to provide a valid function name (letters, numbers, - or _)') unless @function_name.match(/^[a-zA-Z\-_0-9]{1,}$/)
37
+ end
38
+
39
+ def write_yaml
40
+ write_file("./faastruby.yml", @yaml_content.to_yaml)
41
+ end
42
+
43
+ def write_gemfile
44
+ content = "\n# Added by 'faastruby upgrade'\ngroup :test do\n gem 'rspec'\nend\n"
45
+ write_file("./Gemfile", content, 'a')
46
+ end
47
+
48
+ def copy_spec_folder
49
+ @base_dir = '.'
50
+ source = "#{Gem::Specification.find_by_name("faastruby").gem_dir}/example-blank"
51
+ FileUtils.cp_r("#{source}/spec", "#{@base_dir}/")
52
+ puts "+ d #{@base_dir}/spec".green
53
+ puts "+ d #{@base_dir}/spec/helpers".green
54
+ puts "+ f #{@base_dir}/spec/helpers/faastruby.rb".green
55
+ puts "+ f #{@base_dir}/spec/handler_spec.rb".green
56
+ puts "+ f #{@base_dir}/spec/spec_helper.rb".green
57
+ end
58
+
59
+ def self.help
60
+ "upgrade".blue
61
+ end
62
+
63
+ def usage
64
+ "Usage: faastruby #{self.class.help}"
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,31 @@
1
+ module FaaStRuby
2
+ module Command
3
+ class Help < BaseCommand
4
+ def initialize(args)
5
+ @args = args
6
+ end
7
+
8
+ def run
9
+ puts "FaaStRuby CLI - Manage workspaces and functions hosted at faastruby.io"
10
+ puts
11
+ puts 'help, -h, --help # Displays this help'
12
+ puts '-v # Print version and exit'
13
+ puts
14
+ workspaces = ["Workspaces:"]
15
+ functions = ["Functions:"]
16
+ FaaStRuby::Command::COMMANDS.each do |command, klass|
17
+ next if command == 'upgrade'
18
+ next if klass.to_s.match(/.+Command::Help$/)
19
+ next if klass.to_s.match(/.+Command::Version$/)
20
+ section = functions if klass.to_s.match(/.+::Function::.+/)
21
+ section = workspaces if klass.to_s.match(/.+::Workspace::.+/)
22
+ section << " #{klass.help}"
23
+ end
24
+ puts workspaces
25
+ puts
26
+ puts functions
27
+ puts
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module FaaStRuby
2
+ module Command
3
+ class Version < BaseCommand
4
+ def initialize(args)
5
+ @args = args
6
+ end
7
+
8
+ def run
9
+ puts FaaStRuby::VERSION
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Workspace
4
+ class WorkspaceBaseCommand < BaseCommand
5
+ end
6
+ end
7
+ end
8
+ end
9
+
10
+ require 'faastruby/cli/commands/workspace/create'
11
+ require 'faastruby/cli/commands/workspace/destroy'
12
+ require 'faastruby/cli/commands/workspace/list'
@@ -0,0 +1,70 @@
1
+ module FaaStRuby
2
+ module Command
3
+ module Workspace
4
+ class Create < WorkspaceBaseCommand
5
+ def initialize(args)
6
+ @args = args
7
+ @missing_args = []
8
+ FaaStRuby::CLI.error(@missing_args, color: nil) if missing_args.any?
9
+ @workspace_name = @args.shift
10
+ parse_options
11
+ @options['credentials_file'] ||= FAASTRUBY_CREDENTIALS
12
+ end
13
+
14
+ def run
15
+ spinner = spin("Requesting credentials...")
16
+ workspace = FaaStRuby::Workspace.create(name: @workspace_name, email: @options['email'])
17
+ spinner.stop("Done!")
18
+ FaaStRuby::CLI.error(workspace.errors) if workspace.errors.any?
19
+ if @options['stdout']
20
+ 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
21
+ puts "API_KEY: #{workspace.credentials['api_key']}"
22
+ puts "API_SECRET: #{workspace.credentials['api_secret']}"
23
+ else
24
+ puts "Writing credentials to #{@options['credentials_file']}"
25
+ FaaStRuby::Credentials.add(@workspace_name, workspace.credentials, @options['credentials_file'])
26
+ end
27
+ puts "Workspace '#{@workspace_name}' created"
28
+ end
29
+
30
+ def self.help
31
+ "create-workspace".blue + " WORKSPACE_NAME [--stdout|-o, --output-file] [-e, --email YOUR_EMAIL_ADDRESS]"
32
+ end
33
+
34
+ def usage
35
+ "Usage: faastruby #{self.class.help}"
36
+ end
37
+
38
+ private
39
+
40
+ def missing_args
41
+ if @args.empty?
42
+ @missing_args << "Missing argument: WORKSPACE_NAME".red
43
+ @missing_args << "Usage: faastruby create-workspace WORKSPACE_NAME"
44
+ end
45
+ FaaStRuby::CLI.error(["'#{@args.first}' is not a valid workspace name.".red, usage], color: nil) if @args.first =~ /^-.*/
46
+ @missing_args
47
+ end
48
+
49
+ def parse_options
50
+ @options = {}
51
+ while @args.any?
52
+ option = @args.shift
53
+ case option
54
+ # when '--file'
55
+ # @options['credentials_file'] = @args.shift
56
+ when '--stdout'
57
+ @options['stdout'] = true
58
+ when '-o', '--output-file'
59
+ @options['credentials_file'] = @args.shift
60
+ when '-e', '--email'
61
+ @options['email'] = @args.shift
62
+ else
63
+ FaaStRuby.error("Unknown argument: #{option}")
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end