faastruby 0.2.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 (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