aws-rails-provisioner 0.0.0.rc1

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,90 @@
1
+ require 'set'
2
+
3
+ module Aws::RailsProvisioner
4
+ # @api private
5
+ class Service
6
+
7
+ def initialize(name, options = {})
8
+ @name = name.to_s
9
+ @file_path = options[:file_path] || 'aws-rails-provisioner.yml'
10
+ @stack_prefix = _camel_case(@name)
11
+ @path_prefix = _path_prefix(@name)
12
+ @const_prefix = _const_prefix(@stack_prefix)
13
+ @enable_cicd = !!options[:enable_cicd]
14
+ @profile = options[:profile]
15
+ @packages = Set.new
16
+
17
+ # fargate stack
18
+ @source_path = options.fetch(:source_path)
19
+ @fargate = options[:fargate] || {}
20
+
21
+ @db_cluster = options[:db_cluster]
22
+ @scaling = options[:scaling]
23
+
24
+ # pipeline stack
25
+ @cicd = options[:cicd] || {}
26
+ end
27
+
28
+ # @return [String]
29
+ attr_reader :name
30
+
31
+ # @return [String]
32
+ attr_reader :stack_prefix
33
+
34
+ # @return [String]
35
+ attr_reader :path_prefix
36
+
37
+ # @return [String]
38
+ attr_reader :const_prefix
39
+
40
+ # @return [Boolean]
41
+ attr_reader :enable_cicd
42
+
43
+ # @return [Set]
44
+ attr_reader :packages
45
+
46
+ def fargate_stack
47
+ stack = Aws::RailsProvisioner::Views::FargateStack.new(
48
+ file_path: @file_path,
49
+ service_name: @name,
50
+ path_prefix: @path_prefix,
51
+ stack_prefix: @stack_prefix,
52
+ profile: @profile,
53
+ source_path: @source_path,
54
+ db_cluster: @db_cluster,
55
+ fargate: @fargate,
56
+ scaling: @scaling,
57
+ )
58
+ @packages.merge(stack.packages)
59
+ stack.render
60
+ end
61
+
62
+ def pipeline_stack
63
+ if @db_cluster.nil? || @db_cluster.empty?
64
+ @cicd[:skip_migration] = true
65
+ end
66
+ @cicd[:source_path] = @source_path
67
+ @cicd[:stack_prefix] = @stack_prefix
68
+ stack = Aws::RailsProvisioner::Views::PipelineStack.new(@cicd)
69
+ @packages.merge(stack.packages)
70
+ stack.render
71
+ end
72
+
73
+ private
74
+
75
+ def _camel_case(str)
76
+ str.split('_').collect(&:capitalize).join
77
+ end
78
+
79
+ def _path_prefix(str)
80
+ str.downcase.gsub('_', '-')
81
+ end
82
+
83
+ def _const_prefix(str)
84
+ dup = str.dup
85
+ dup[0] = dup[0].downcase
86
+ dup
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,44 @@
1
+ module Aws::RailsProvisioner
2
+ # @api private
3
+ class ServiceEnumerator
4
+
5
+ include Enumerable
6
+
7
+ def initialize(options = {})
8
+ @configs = options || {}
9
+ end
10
+
11
+ # @param [String] name
12
+ def [](name)
13
+ if services.key?(name)
14
+ services[name]
15
+ else
16
+ msg = "unknown service #{identifier.inspect} under :services"
17
+ raise Aws::RailsProvisioner::ValidationError, msg
18
+ end
19
+ end
20
+ alias service []
21
+
22
+ def each(&block)
23
+ services.values.each(&block)
24
+ end
25
+
26
+ private
27
+
28
+ def services
29
+ @service ||= begin
30
+ @configs.inject({}) do |hash, (name, config)|
31
+ hash[name] = build_service(name, config)
32
+ hash
33
+ end
34
+ end
35
+ end
36
+
37
+ def build_service(name, config)
38
+ Aws::RailsProvisioner::Service.new(name, config)
39
+ end
40
+
41
+ end
42
+
43
+ Services = ServiceEnumerator.new
44
+ end
@@ -0,0 +1,20 @@
1
+ module Aws::RailsProvisioner
2
+ class SubnetSelection
3
+
4
+ def initialize(options = {})
5
+ @name = options[:name]
6
+ @type = Aws::RailsProvisioner::Util.subnet_type(options[:type]) if options[:type]
7
+ if @name && @type
8
+ msg = "At most one of :type and :name can be supplied."
9
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
10
+ end
11
+ end
12
+
13
+ # @return [String]
14
+ attr_reader :name
15
+
16
+ # @return [String]
17
+ attr_reader :type
18
+
19
+ end
20
+ end
@@ -0,0 +1,89 @@
1
+ require 'yaml'
2
+
3
+ module Aws::RailsProvisioner
4
+ # @api private
5
+ module Utils
6
+
7
+ def self.ip_address_type(str)
8
+ types = %w(ipv4, dualstack)
9
+ if types.include?(str.downcase)
10
+ str.upcase
11
+ else
12
+ msg = "Unsupported ip address type, please choose from #{types}"
13
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
14
+ end
15
+ end
16
+
17
+ def self.subnet_type(str)
18
+ types = %w(isolated private public)
19
+ if types.include?(str.downcase)
20
+ str.upcase
21
+ else
22
+ msg = "Unsupported subnet type, please choose from #{types}"
23
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
24
+ end
25
+ end
26
+
27
+ def self.removal_policy(str)
28
+ types = %w(retain destroy)
29
+ if types.include?(str.downcase)
30
+ str.upcase
31
+ else
32
+ msg = "Unsupported removal policy, please choose from #{types}"
33
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
34
+ end
35
+ end
36
+
37
+ def self.protocol(str)
38
+ types = %w(https http tcp tls)
39
+ if types.include?(str.downcase)
40
+ str.upcase
41
+ else
42
+ msg = "Unsupported protocol type, please choose from #{types}"
43
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
44
+ end
45
+ end
46
+
47
+ def self.adjustment_type(str)
48
+ types = %w(change_in_capacity percent_change_in_capacity exact_capacity)
49
+ if types.include?(str.downcase)
50
+ str.upcase
51
+ else
52
+ msg = "Unsupported adjustment type, please choose from #{types}"
53
+ raise Aws::RailsProvisioner::Errors::ValidationError, msg
54
+ end
55
+ end
56
+
57
+ def self.parse(file_path)
58
+ config = YAML.load(File.read(file_path))
59
+ symbolize_keys(config)
60
+ rescue
61
+ raise Aws::RailsProvisioner::Errors::InvalidYAMLFile.new
62
+ end
63
+
64
+ def self.to_pairs(hash)
65
+ hash.inject([]) do |arr, (key, value)|
66
+ arr << "'#{key}': '#{value}',"
67
+ arr
68
+ end
69
+ end
70
+
71
+ def self.to_pkgs(services)
72
+ services.inject([]) do |pkgs, svc|
73
+ pkgs << "@aws-cdk/aws-#{svc}"
74
+ pkgs
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def self.symbolize_keys(hash)
81
+ hash.inject({}) do |h, (k,v)|
82
+ v = symbolize_keys(v) if v.respond_to?(:keys)
83
+ h[k.to_sym] = v
84
+ h
85
+ end
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,5 @@
1
+ module Aws
2
+ module RailsProvisioner
3
+ VERSION = '0.0.0.rc1'
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ require 'mustache'
2
+
3
+ module Aws::RailsProvisioner
4
+ # @api private
5
+ class View < Mustache
6
+
7
+ TEMPLATE_DIR = File.expand_path('../../../templates', __FILE__)
8
+
9
+ def self.inherited(subclass)
10
+ parts = subclass.name.split('::')
11
+ parts.shift #=> remove AWS
12
+ parts.shift #=> remove RailsProvisioner
13
+ parts.shift #=> remove Views
14
+ path = parts.map { |part| underscore(part) }.join('/')
15
+ subclass.template_path = TEMPLATE_DIR
16
+ subclass.template_file = "#{TEMPLATE_DIR}/#{path}.mustache"
17
+ subclass.raise_on_context_miss = true
18
+ end
19
+
20
+ private
21
+
22
+ def underscore(str)
23
+ string = str.dup
24
+ string.scan(/[a-z0-9]+|\d+|[A-Z0-9]+[a-z]*/).join('_'.freeze)
25
+ string.downcase!
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,100 @@
1
+ module Aws::RailsProvisioner
2
+ module Views
3
+
4
+ class FargateStack < View
5
+
6
+ # Fargate Stack Generation
7
+ #
8
+ # @param [Hash] options
9
+ #
10
+ # @option options [String] :source_path relative path from `aws-rails-provisioner.yml`
11
+ # to the directory containing Rails Application source
12
+ #
13
+ # @option options [Hash] :db_cluster
14
+ # @see {Aws::RailsProvisioner::DBCluster}
15
+ #
16
+ # @option options [Hash] :fargate configurations for
17
+ # fargate service.
18
+ # @see {Aws::RailsProvisioner::Fargate}
19
+ #
20
+ # @option options [Hash] :scaling configurations for
21
+ # scaling setting for Fargate service
22
+ # @see {Aws::RailsProvisioner::Scaling}
23
+ #
24
+ def initialize(options = {})
25
+ # code gen only
26
+ @service_name = options[:service_name]
27
+ @path_prefix = options[:path_prefix]
28
+ @stack_prefix = options[:stack_prefix]
29
+ @profile = options[:profile]
30
+
31
+ dir = File.dirname(File.expand_path(options[:file_path]))
32
+ @source_path = File.join(dir, options[:source_path])
33
+ @rds_config = options[:db_cluster] || {}
34
+ @fargate_config = options[:fargate] || {}
35
+ @scaling_config = options[:scaling] || {}
36
+ end
37
+
38
+ # @return [String]
39
+ attr_reader :stack_prefix
40
+
41
+ # @return [String]
42
+ attr_reader :source_path
43
+
44
+ def services
45
+ base = [
46
+ { abbr: 'ec2', value: 'ec2' },
47
+ { abbr: 'ecs', value: 'ecs' },
48
+ { abbr: 'ecr', value: 'ecr' },
49
+ { abbr: 'ecs_patterns', value: 'ecs-patterns' },
50
+ { abbr: 'ecr_assets', value: 'ecr-assets' },
51
+ { abbr: 'rds', value: 'rds' }
52
+ ]
53
+ if @fargate_config && @fargate_config[:certificate]
54
+ base << { abbr: 'certificatemanager', value: 'certificatemanager' }
55
+ end
56
+ if @scaling_config &&
57
+ (@scaling_config[:on_metric] || @scaling_config[:on_custom_metric])
58
+ base << { abbr: 'cloudwatch', value: 'cloudwatch' }
59
+ end
60
+ if @rds_config && !@rds_config.empty?
61
+ base << { abbr: 'secretsmanager', value: 'secretsmanager' }
62
+ if @rds_config[:kms_key_arn]
63
+ base << { abbr: 'kms', value: 'kms'}
64
+ end
65
+ end
66
+ base
67
+ end
68
+
69
+ def packages
70
+ keys = services.map {|svc| svc[:value] }
71
+ Aws::RailsProvisioner::Utils.to_pkgs(keys)
72
+ end
73
+
74
+ def db_cluster
75
+ if @rds_config && !@rds_config.empty?
76
+ unless @rds_config[:username]
77
+ @rds_config[:username] = "#{stack_prefix}DBAdminUser"
78
+ end
79
+ @rds_config[:profile] = @profile if @profile
80
+ Aws::RailsProvisioner::DBCluster.new(@rds_config)
81
+ end
82
+ end
83
+
84
+ def fargate
85
+ if @rds_config && !@rds_config.empty?
86
+ @fargate_config[:has_db] = true
87
+ end
88
+ @fargate_config[:service_name] = @stack_prefix
89
+ Aws::RailsProvisioner::Fargate.new(@fargate_config)
90
+ end
91
+
92
+ def scaling
93
+ if @scaling_config && !@scaling_config.empty?
94
+ Aws::RailsProvisioner::Scaling.new(@scaling_config)
95
+ end
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,35 @@
1
+ module Aws::RailsProvisioner
2
+ module Views
3
+ class InitStack < View
4
+
5
+ # For InitStack Generation
6
+ #
7
+ # @param [Hash] options
8
+ #
9
+ # @option options [Hash] :vpc
10
+ # @see {Aws::RailsProvisioner::Vpc}
11
+ #
12
+ def initialize(options = {})
13
+ @vpc_config = options[:vpc]
14
+ @stack_prefix = options[:stack_prefix]
15
+ end
16
+
17
+ # @api private
18
+ # @return [String]
19
+ attr_reader :stack_prefix
20
+
21
+ def services
22
+ ['ec2', 'ecs']
23
+ end
24
+
25
+ def packages
26
+ Aws::RailsProvisioner::Utils.to_pkgs(services)
27
+ end
28
+
29
+ def vpc
30
+ Aws::RailsProvisioner::Vpc.new(@vpc_config)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,107 @@
1
+ module Aws::RailsProvisioner
2
+ module Views
3
+ class PipelineStack < View
4
+
5
+ # Pipeline (CICD) Generation under :cicd
6
+ #
7
+ # @param [Hash] options
8
+ #
9
+ # @option options [String] :pipeline_name Name for the
10
+ # AWS CodePipeline generated
11
+ #
12
+ # @option options [String] :source_repo CodeCommit Repo
13
+ # name for holding your rails app source, default to
14
+ # folder name where your rails app lives
15
+ #
16
+ # @option options [String] :source_description Description for
17
+ # the CodeCommit Repo, default to 'created by aws-rails-provisioner'
18
+ #
19
+ # @option options [Hash] :build configurations for codebuild project
20
+ # for building images
21
+ # @see {Aws::RailsProvisioner::Build}
22
+ #
23
+ # @option options [Hash] :migration configuration for db migration
24
+ # codebuild, available if :db_cluster is configured
25
+ # @see {Aws::RailsProvisioner::Migration}
26
+ #
27
+ def initialize(options = {})
28
+ @stack_prefix = options[:stack_prefix]
29
+
30
+ @pipeline_name = options[:pipeline_name] || "#{@stack_prefix}Pipeline"
31
+ @source_repo = options[:source_repo] || _extract_repo_name(options[:source_path])
32
+ @source_description = options[:source_description] || "created by aws-rails-provisioner with AWS CDK for #{@stack_prefix}"
33
+
34
+ @build_config = options[:build] || {}
35
+ unless @build_config[:project_name]
36
+ @build_config[:project_name] = "#{@stack_prefix}ImageBuild"
37
+ end
38
+
39
+ @skip_migration = options[:skip_migration] || false
40
+ unless @skip_migration
41
+ @migration_config = options[:migration] || {}
42
+ unless @migration_config[:project_name]
43
+ @migration_config[:project_name] = "#{@stack_prefix}DBMigration"
44
+ end
45
+ end
46
+ end
47
+
48
+ def services
49
+ [
50
+ { abbr: 'iam', value: 'iam'},
51
+ { abbr: 'ec2', value: 'ec2'},
52
+ { abbr: 'ecr', value: 'ecr' },
53
+ { abbr: 'ecs', value: 'ecs' },
54
+ { abbr: 'rds', value: 'rds' },
55
+ { abbr: 'codebuild', value: 'codebuild'},
56
+ { abbr: 'codecommit', value: 'codecommit'},
57
+ { abbr: 'codepipeline', value: 'codepipeline' },
58
+ { abbr: 'pipelineactions', value: 'codepipeline-actions'}
59
+ ]
60
+ end
61
+
62
+ def packages
63
+ keys = services.map {|svc| svc[:value] }
64
+ Aws::RailsProvisioner::Utils.to_pkgs(keys)
65
+ end
66
+
67
+ # @return [String]
68
+ attr_reader :stack_prefix
69
+
70
+ # @return [String]
71
+ attr_reader :pipeline_name
72
+
73
+ # @return [String]
74
+ attr_reader :source_repo
75
+
76
+ # @return [String]
77
+ attr_reader :source_description
78
+
79
+ # @return [Aws::RailsProvisioner::Build]
80
+ attr_reader :build
81
+
82
+ # @return [Aws::RailsProvisioner::Migration]
83
+ attr_reader :migration
84
+
85
+ # @return [Boolean]
86
+ attr_reader :skip_migration
87
+
88
+ def build
89
+ Aws::RailsProvisioner::Build.new(@build_config)
90
+ end
91
+
92
+ def migration
93
+ if @migration_config
94
+ Aws::RailsProvisioner::Migration.new(@migration_config)
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def _extract_repo_name(path)
101
+ path.split('/')[-1] || 'AwsRailsProvisionerRailsAppSource'
102
+ end
103
+
104
+ end
105
+ end
106
+ end
107
+