dslh 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/spec/dslh_spec.rb CHANGED
@@ -1,4 +1,8 @@
1
1
  describe Dslh do
2
+ let(:drupal_multi_az_template) do
3
+ open(File.expand_path('../Drupal_Multi_AZ.template', __FILE__)) {|f| f.read }
4
+ end
5
+
2
6
  it 'should be empty hash' do
3
7
  h = Dslh.eval {}
4
8
  expect(h).to eq({})
@@ -497,12 +501,1190 @@ end
497
501
  end
498
502
 
499
503
  it 'should convert json to dsl' do
500
- url = 'https://s3.amazonaws.com/cloudformation-templates-us-east-1/Drupal_Multi_AZ.template'
501
- template = open(url) {|f| f.read }
502
- template = JSON.parse(template)
504
+ template = JSON.parse(drupal_multi_az_template)
503
505
 
504
506
  dsl = Dslh.deval(template)
505
507
  evaluated = Dslh.eval(dsl, :key_conv => proc {|i| i.to_s })
506
508
  expect(evaluated).to eq(template)
507
509
  end
510
+
511
+ it 'should convert json to dsl with key_conf' do
512
+ template = JSON.parse(drupal_multi_az_template)
513
+
514
+ key_conv = proc do |k|
515
+ k.to_s.gsub('::', '__')
516
+ end
517
+
518
+ dsl = Dslh.deval(template, :key_conv => key_conv)
519
+
520
+ expect(dsl).to eq(<<-'EOS')
521
+ AWSTemplateFormatVersion "2010-09-09"
522
+ Description "AWS CloudFormation Sample Template Drupal_Multi_AZ. Drupal is an open source content management platform powering millions of websites and applications. This template installs a highly-available, scalable Drupal deployment using a multi-az Amazon RDS database instance for storage. It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time. **WARNING** This template creates one or more Amazon EC2 instances, an Elastic Load Balancer and an Amazon RDS database. You will be billed for the AWS resources used if you create a stack from this template."
523
+ Parameters do
524
+ KeyName do
525
+ Description "Name of an existing EC2 KeyPair to enable SSH access to the instances"
526
+ Type "String"
527
+ MinLength "1"
528
+ MaxLength "255"
529
+ AllowedPattern "[\\x20-\\x7E]*"
530
+ ConstraintDescription "can contain only ASCII characters."
531
+ end
532
+ InstanceType do
533
+ Description "WebServer EC2 instance type"
534
+ Type "String"
535
+ Default "m1.small"
536
+ ConstraintDescription "must be a valid EC2 instance type."
537
+ end
538
+ SiteName do
539
+ Default "My Site"
540
+ Description "The name of the Drupal Site"
541
+ Type "String"
542
+ end
543
+ SiteEMail do
544
+ Description "EMail for site adminitrator"
545
+ Type "String"
546
+ end
547
+ SiteAdmin do
548
+ Description "The Drupal site admin account username"
549
+ Type "String"
550
+ MinLength "1"
551
+ MaxLength "16"
552
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
553
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
554
+ end
555
+ SitePassword do
556
+ NoEcho "true"
557
+ Description "The Drupal site admin account password"
558
+ Type "String"
559
+ MinLength "1"
560
+ MaxLength "41"
561
+ AllowedPattern "[a-zA-Z0-9]*"
562
+ ConstraintDescription "must contain only alphanumeric characters."
563
+ end
564
+ DBName do
565
+ Default "drupaldb"
566
+ Description "The Drupal database name"
567
+ Type "String"
568
+ MinLength "1"
569
+ MaxLength "64"
570
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
571
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
572
+ end
573
+ DBUsername do
574
+ Default "admin"
575
+ NoEcho "true"
576
+ Description "The Drupal database admin account username"
577
+ Type "String"
578
+ MinLength "1"
579
+ MaxLength "16"
580
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
581
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
582
+ end
583
+ DBPassword do
584
+ Default "password"
585
+ NoEcho "true"
586
+ Description "The Drupal database admin account password"
587
+ Type "String"
588
+ MinLength "8"
589
+ MaxLength "41"
590
+ AllowedPattern "[a-zA-Z0-9]*"
591
+ ConstraintDescription "must contain only alphanumeric characters."
592
+ end
593
+ DBClass do
594
+ Default "db.m1.small"
595
+ Description "Database instance class"
596
+ Type "String"
597
+ AllowedValues "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge"
598
+ ConstraintDescription "must select a valid database instance type."
599
+ end
600
+ DBAllocatedStorage do
601
+ Default "5"
602
+ Description "The size of the database (Gb)"
603
+ Type "Number"
604
+ MinValue "5"
605
+ MaxValue "1024"
606
+ ConstraintDescription "must be between 5 and 1024Gb."
607
+ end
608
+ MultiAZDatabase do
609
+ Default "true"
610
+ Description "Create a multi-AZ MySQL Amazon RDS database instance"
611
+ Type "String"
612
+ AllowedValues "true", "false"
613
+ ConstraintDescription "must be either true or false."
614
+ end
615
+ WebServerCapacity do
616
+ Default "2"
617
+ Description "The initial number of WebServer instances"
618
+ Type "Number"
619
+ MinValue "1"
620
+ MaxValue "5"
621
+ ConstraintDescription "must be between 1 and 5 EC2 instances."
622
+ end
623
+ SSHLocation do
624
+ Description "The IP address range that can be used to SSH to the EC2 instances"
625
+ Type "String"
626
+ MinLength "9"
627
+ MaxLength "18"
628
+ Default "0.0.0.0/0"
629
+ AllowedPattern "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
630
+ ConstraintDescription "must be a valid IP CIDR range of the form x.x.x.x/x."
631
+ end
632
+ end
633
+ Mappings do
634
+ AWSInstanceType2Arch(
635
+ {"t1.micro"=>{"Arch"=>"64"},
636
+ "m1.small"=>{"Arch"=>"64"},
637
+ "m1.medium"=>{"Arch"=>"64"},
638
+ "m1.large"=>{"Arch"=>"64"},
639
+ "m1.xlarge"=>{"Arch"=>"64"},
640
+ "m2.xlarge"=>{"Arch"=>"64"},
641
+ "m2.2xlarge"=>{"Arch"=>"64"},
642
+ "m2.4xlarge"=>{"Arch"=>"64"},
643
+ "m3.xlarge"=>{"Arch"=>"64"},
644
+ "m3.2xlarge"=>{"Arch"=>"64"},
645
+ "c1.medium"=>{"Arch"=>"64"},
646
+ "c1.xlarge"=>{"Arch"=>"64"},
647
+ "cc1.4xlarge"=>{"Arch"=>"64HVM"},
648
+ "cc2.8xlarge"=>{"Arch"=>"64HVM"},
649
+ "cg1.4xlarge"=>{"Arch"=>"64HVM"}})
650
+ AWSRegionArch2AMI(
651
+ {"us-east-1"=>
652
+ {"32"=>"ami-a0cd60c9", "64"=>"ami-aecd60c7", "64HVM"=>"ami-a8cd60c1"},
653
+ "us-west-2"=>
654
+ {"32"=>"ami-46da5576", "64"=>"ami-48da5578", "64HVM"=>"NOT_YET_SUPPORTED"},
655
+ "us-west-1"=>
656
+ {"32"=>"ami-7d4c6938", "64"=>"ami-734c6936", "64HVM"=>"NOT_YET_SUPPORTED"},
657
+ "eu-west-1"=>
658
+ {"32"=>"ami-61555115", "64"=>"ami-6d555119", "64HVM"=>"ami-67555113"},
659
+ "ap-southeast-1"=>
660
+ {"32"=>"ami-220b4a70", "64"=>"ami-3c0b4a6e", "64HVM"=>"NOT_YET_SUPPORTED"},
661
+ "ap-southeast-2"=>
662
+ {"32"=>"ami-8f990eb5", "64"=>"ami-95990eaf", "64HVM"=>"NOT_YET_SUPPORTED"},
663
+ "ap-northeast-1"=>
664
+ {"32"=>"ami-2a19aa2b", "64"=>"ami-2819aa29", "64HVM"=>"NOT_YET_SUPPORTED"},
665
+ "sa-east-1"=>
666
+ {"32"=>"ami-f836e8e5", "64"=>"ami-fe36e8e3", "64HVM"=>"NOT_YET_SUPPORTED"}})
667
+ end
668
+ Resources do
669
+ S3Bucket do
670
+ Type "AWS::S3::Bucket"
671
+ DeletionPolicy "Retain"
672
+ end
673
+ BucketPolicy do
674
+ Type "AWS::S3::BucketPolicy"
675
+ Properties do
676
+ PolicyDocument do
677
+ Version "2008-10-17"
678
+ Id "UploadPolicy"
679
+ Statement [
680
+ _{
681
+ Sid "EnableReadWrite"
682
+ Action "s3:GetObject", "s3:PutObject", "s3:PutObjectACL"
683
+ Effect "Allow"
684
+ Resource do
685
+ Fn__Join [
686
+ "",
687
+ ["arn:aws:s3:::", {"Ref"=>"S3Bucket"}, "/*"]
688
+ ]
689
+ end
690
+ Principal do
691
+ AWS do
692
+ Fn__GetAtt "S3User", "Arn"
693
+ end
694
+ end
695
+ }
696
+ ]
697
+ end
698
+ Bucket do
699
+ Ref "S3Bucket"
700
+ end
701
+ end
702
+ end
703
+ S3User do
704
+ Type "AWS::IAM::User"
705
+ Properties do
706
+ Path "/"
707
+ Policies [
708
+ _{
709
+ PolicyName "root"
710
+ PolicyDocument do
711
+ Statement [
712
+ _{
713
+ Effect "Allow"
714
+ Action "s3:*"
715
+ Resource "*"
716
+ }
717
+ ]
718
+ end
719
+ }
720
+ ]
721
+ end
722
+ end
723
+ S3Keys do
724
+ Type "AWS::IAM::AccessKey"
725
+ Properties do
726
+ UserName do
727
+ Ref "S3User"
728
+ end
729
+ end
730
+ end
731
+ ElasticLoadBalancer do
732
+ Type "AWS::ElasticLoadBalancing::LoadBalancer"
733
+ Metadata do
734
+ Comment "Configure the Load Balancer with a simple health check and cookie-based stickiness"
735
+ end
736
+ Properties do
737
+ AvailabilityZones do
738
+ Fn__GetAZs ""
739
+ end
740
+ LBCookieStickinessPolicy [
741
+ _{
742
+ PolicyName "CookieBasedPolicy"
743
+ CookieExpirationPeriod "30"
744
+ }
745
+ ]
746
+ Listeners [
747
+ _{
748
+ LoadBalancerPort "80"
749
+ InstancePort "80"
750
+ Protocol "HTTP"
751
+ PolicyNames ["CookieBasedPolicy"]
752
+ }
753
+ ]
754
+ HealthCheck do
755
+ Target "HTTP:80/"
756
+ HealthyThreshold "2"
757
+ UnhealthyThreshold "5"
758
+ Interval "10"
759
+ Timeout "5"
760
+ end
761
+ end
762
+ end
763
+ WebServerGroup do
764
+ Type "AWS::AutoScaling::AutoScalingGroup"
765
+ Properties do
766
+ AvailabilityZones do
767
+ Fn__GetAZs ""
768
+ end
769
+ LaunchConfigurationName do
770
+ Ref "LaunchConfig"
771
+ end
772
+ MinSize "1"
773
+ MaxSize "5"
774
+ DesiredCapacity do
775
+ Ref "WebServerCapacity"
776
+ end
777
+ LoadBalancerNames [
778
+ _{
779
+ Ref "ElasticLoadBalancer"
780
+ }
781
+ ]
782
+ end
783
+ end
784
+ LaunchConfig do
785
+ Type "AWS::AutoScaling::LaunchConfiguration"
786
+ Metadata do
787
+ AWS__CloudFormation__Init do
788
+ config do
789
+ packages do
790
+ yum(
791
+ {"httpd"=>[],
792
+ "php"=>[],
793
+ "php-mysql"=>[],
794
+ "php-gd"=>[],
795
+ "php-xml"=>[],
796
+ "php-mbstring"=>[],
797
+ "mysql"=>[],
798
+ "gcc"=>[],
799
+ "make"=>[],
800
+ "libstdc++-devel"=>[],
801
+ "gcc-c++"=>[],
802
+ "fuse"=>[],
803
+ "fuse-devel"=>[],
804
+ "libcurl-devel"=>[],
805
+ "libxml2-devel"=>[],
806
+ "openssl-devel"=>[],
807
+ "mailcap"=>[]})
808
+ end
809
+ sources(
810
+ {"/var/www/html"=>"http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz",
811
+ "/home/ec2-user"=>"http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz",
812
+ "/home/ec2-user/s3fs"=>"http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz"})
813
+ files(
814
+ {"/etc/passwd-s3fs"=>
815
+ {"content"=>
816
+ {"Fn::Join"=>
817
+ ["",
818
+ [{"Ref"=>"S3Keys"},
819
+ ":",
820
+ {"Fn::GetAtt"=>["S3Keys", "SecretAccessKey"]},
821
+ "\n"]]},
822
+ "mode"=>"000400",
823
+ "owner"=>"root",
824
+ "group"=>"root"},
825
+ "/home/ec2-user/settings.php"=>
826
+ {"content"=>
827
+ {"Fn::Join"=>
828
+ ["",
829
+ ["<?php\n",
830
+ "\n",
831
+ "$databases = array (\n",
832
+ " 'default' =>\n",
833
+ " array (\n",
834
+ " 'default' =>\n",
835
+ " array (\n",
836
+ " 'database' => '",
837
+ {"Ref"=>"DBName"},
838
+ "',\n",
839
+ " 'username' => '",
840
+ {"Ref"=>"DBUsername"},
841
+ "',\n",
842
+ " 'password' => '",
843
+ {"Ref"=>"DBPassword"},
844
+ "',\n",
845
+ " 'host' => '",
846
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Address"]},
847
+ "',\n",
848
+ " 'port' => '",
849
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Port"]},
850
+ "',\n",
851
+ " 'driver' => 'mysql',\n",
852
+ " 'prefix' => 'drupal_',\n",
853
+ " ),\n",
854
+ " ),\n",
855
+ ");\n",
856
+ "\n",
857
+ "$update_free_access = FALSE;\n",
858
+ "\n",
859
+ "$drupal_hash_salt = '0c3R8noNALe3shsioQr5hK1dMHdwRfikLoSfqn0_xpA';\n",
860
+ "\n",
861
+ "ini_set('session.gc_probability', 1);\n",
862
+ "ini_set('session.gc_divisor', 100);\n",
863
+ "ini_set('session.gc_maxlifetime', 200000);\n",
864
+ "ini_set('session.cookie_lifetime', 2000000);\n"]]},
865
+ "mode"=>"000400",
866
+ "owner"=>"root",
867
+ "group"=>"root"}})
868
+ services do
869
+ sysvinit do
870
+ httpd do
871
+ enabled "true"
872
+ ensureRunning "true"
873
+ end
874
+ sendmail do
875
+ enabled "false"
876
+ ensureRunning "false"
877
+ end
878
+ end
879
+ end
880
+ end
881
+ end
882
+ end
883
+ Properties do
884
+ ImageId do
885
+ Fn__FindInMap [
886
+ "AWSRegionArch2AMI",
887
+ _{
888
+ Ref "AWS::Region"
889
+ },
890
+ _{
891
+ Fn__FindInMap [
892
+ "AWSInstanceType2Arch",
893
+ _{
894
+ Ref "InstanceType"
895
+ },
896
+ "Arch"
897
+ ]
898
+ }
899
+ ]
900
+ end
901
+ InstanceType do
902
+ Ref "InstanceType"
903
+ end
904
+ SecurityGroups [
905
+ _{
906
+ Ref "WebServerSecurityGroup"
907
+ }
908
+ ]
909
+ KeyName do
910
+ Ref "KeyName"
911
+ end
912
+ UserData do
913
+ Fn__Base64 do
914
+ Fn__Join [
915
+ "",
916
+ ["#!/bin/bash -v\n",
917
+ "yum update -y aws-cfn-bootstrap\n",
918
+ "# Helper function\n",
919
+ "function error_exit\n",
920
+ "{\n",
921
+ " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '",
922
+ {"Ref"=>"WaitHandle"},
923
+ "'\n",
924
+ " exit 1\n",
925
+ "}\n",
926
+ "# Install Apache Web Server, MySQL and Drupal\n",
927
+ "/opt/aws/bin/cfn-init -s ",
928
+ {"Ref"=>"AWS::StackId"},
929
+ " -r LaunchConfig ",
930
+ " --region ",
931
+ {"Ref"=>"AWS::Region"},
932
+ " || error_exit 'Failed to run cfn-init'\n",
933
+ "# Install s3fs\n",
934
+ "cd /home/ec2-user/s3fs/s3fs-1.61\n",
935
+ "./configure --prefix=/usr\n",
936
+ "make\n",
937
+ "make install\n",
938
+ "# Move the website files to the top level\n",
939
+ "mv /var/www/html/drupal-7.8/* /var/www/html\n",
940
+ "mv /var/www/html/drupal-7.8/.htaccess /var/www/html\n",
941
+ "rm -Rf /var/www/html/drupal-7.8\n",
942
+ "# Mount the S3 bucket\n",
943
+ "mv /var/www/html/sites/default/files /var/www/html/sites/default/files_original\n",
944
+ "mkdir -p /var/www/html/sites/default/files\n",
945
+ "s3fs -o allow_other -o use_cache=/tmp ",
946
+ {"Ref"=>"S3Bucket"},
947
+ " /var/www/html/sites/default/files || error_exit 'Failed to mount the S3 bucket'\n",
948
+ "echo `hostname` >> /var/www/html/sites/default/files/hosts\n",
949
+ "# Make changes to Apache Web Server configuration\n",
950
+ "sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf\n",
951
+ "service httpd restart\n",
952
+ "# Only execute the site install if we are the first host up - otherwise we'll end up losing all the data\n",
953
+ "read first < /var/www/html/sites/default/files/hosts\n",
954
+ "if [ `hostname` = $first ]\n",
955
+ "then\n",
956
+ " # Create the site in Drupal\n",
957
+ " cd /var/www/html\n",
958
+ " ~ec2-user/drush/drush site-install standard --yes",
959
+ " --site-name='",
960
+ {"Ref"=>"SiteName"},
961
+ "' --site-mail=",
962
+ {"Ref"=>"SiteEMail"},
963
+ " --account-name=",
964
+ {"Ref"=>"SiteAdmin"},
965
+ " --account-pass=",
966
+ {"Ref"=>"SitePassword"},
967
+ " --db-url=mysql://",
968
+ {"Ref"=>"DBUsername"},
969
+ ":",
970
+ {"Ref"=>"DBPassword"},
971
+ "@",
972
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Address"]},
973
+ ":",
974
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Port"]},
975
+ "/",
976
+ {"Ref"=>"DBName"},
977
+ " --db-prefix=drupal_\n",
978
+ " # use the S3 bucket for shared file storage\n",
979
+ " cp -R sites/default/files_original/* sites/default/files\n",
980
+ " cp -R sites/default/files_original/.htaccess sites/default/files\n",
981
+ "else\n",
982
+ " # Copy settings.php file since everything else is configured\n",
983
+ " cp /home/ec2-user/settings.php /var/www/html/sites/default\n",
984
+ "fi\n",
985
+ "rm /home/ec2-user/settings.php\n",
986
+ "# All is well so signal success\n",
987
+ "/opt/aws/bin/cfn-signal -e 0 -r \"Drupal setup complete\" '",
988
+ {"Ref"=>"WaitHandle"},
989
+ "'\n"]
990
+ ]
991
+ end
992
+ end
993
+ end
994
+ end
995
+ WaitHandle do
996
+ Type "AWS::CloudFormation::WaitConditionHandle"
997
+ end
998
+ WaitCondition do
999
+ Type "AWS::CloudFormation::WaitCondition"
1000
+ DependsOn "WebServerGroup"
1001
+ Properties do
1002
+ Handle do
1003
+ Ref "WaitHandle"
1004
+ end
1005
+ Timeout "600"
1006
+ end
1007
+ end
1008
+ DBInstance do
1009
+ Type "AWS::RDS::DBInstance"
1010
+ Properties do
1011
+ DBName do
1012
+ Ref "DBName"
1013
+ end
1014
+ Engine "MySQL"
1015
+ MultiAZ do
1016
+ Ref "MultiAZDatabase"
1017
+ end
1018
+ MasterUsername do
1019
+ Ref "DBUsername"
1020
+ end
1021
+ DBInstanceClass do
1022
+ Ref "DBClass"
1023
+ end
1024
+ DBSecurityGroups [
1025
+ _{
1026
+ Ref "DBSecurityGroup"
1027
+ }
1028
+ ]
1029
+ AllocatedStorage do
1030
+ Ref "DBAllocatedStorage"
1031
+ end
1032
+ MasterUserPassword do
1033
+ Ref "DBPassword"
1034
+ end
1035
+ end
1036
+ end
1037
+ DBSecurityGroup do
1038
+ Type "AWS::RDS::DBSecurityGroup"
1039
+ Properties do
1040
+ DBSecurityGroupIngress do
1041
+ EC2SecurityGroupName do
1042
+ Ref "WebServerSecurityGroup"
1043
+ end
1044
+ end
1045
+ GroupDescription "Frontend Access"
1046
+ end
1047
+ end
1048
+ WebServerSecurityGroup do
1049
+ Type "AWS::EC2::SecurityGroup"
1050
+ Properties do
1051
+ GroupDescription "Enable HTTP access via port 80, locked down to requests from the load balancer only and SSH access"
1052
+ SecurityGroupIngress [
1053
+ _{
1054
+ IpProtocol "tcp"
1055
+ FromPort "80"
1056
+ ToPort "80"
1057
+ SourceSecurityGroupOwnerId do
1058
+ Fn__GetAtt "ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"
1059
+ end
1060
+ SourceSecurityGroupName do
1061
+ Fn__GetAtt "ElasticLoadBalancer", "SourceSecurityGroup.GroupName"
1062
+ end
1063
+ },
1064
+ _{
1065
+ IpProtocol "tcp"
1066
+ FromPort "22"
1067
+ ToPort "22"
1068
+ CidrIp do
1069
+ Ref "SSHLocation"
1070
+ end
1071
+ }
1072
+ ]
1073
+ end
1074
+ end
1075
+ end
1076
+ Outputs do
1077
+ WebsiteURL do
1078
+ Value do
1079
+ Fn__Join [
1080
+ "",
1081
+ ["http://", {"Fn::GetAtt"=>["ElasticLoadBalancer", "DNSName"]}]
1082
+ ]
1083
+ end
1084
+ Description "Drupal Website"
1085
+ end
1086
+ end
1087
+ EOS
1088
+ end
1089
+
1090
+ it 'should convert json to dsl with key_conf (return Proc)' do
1091
+ template = JSON.parse(drupal_multi_az_template)
1092
+
1093
+ exclude_key = proc do |k|
1094
+ k = k.to_s.gsub('::', '__')
1095
+ k !~ /\A[_a-z]\w+\Z/i and k !~ %r|(?:/[:graph:]+)+|
1096
+ end
1097
+
1098
+ key_conv = proc do |k|
1099
+ k = k.to_s
1100
+
1101
+ if k =~ %r|(?:/[:graph:]+)+|
1102
+ proc do |v, nested|
1103
+ if nested
1104
+ "_path(#{k.inspect}) #{v}"
1105
+ else
1106
+ "_path #{k.inspect}, #{v}"
1107
+ end
1108
+ end
1109
+ else
1110
+ k.gsub('::', '__')
1111
+ end
1112
+ end
1113
+
1114
+ dsl = Dslh.deval(template, :key_conv => key_conv, :exclude_key => exclude_key)
1115
+
1116
+ expect(dsl).to eq(<<-'EOS')
1117
+ AWSTemplateFormatVersion "2010-09-09"
1118
+ Description "AWS CloudFormation Sample Template Drupal_Multi_AZ. Drupal is an open source content management platform powering millions of websites and applications. This template installs a highly-available, scalable Drupal deployment using a multi-az Amazon RDS database instance for storage. It uses the AWS CloudFormation bootstrap scripts to install packages and files at instance launch time. **WARNING** This template creates one or more Amazon EC2 instances, an Elastic Load Balancer and an Amazon RDS database. You will be billed for the AWS resources used if you create a stack from this template."
1119
+ Parameters do
1120
+ KeyName do
1121
+ Description "Name of an existing EC2 KeyPair to enable SSH access to the instances"
1122
+ Type "String"
1123
+ MinLength "1"
1124
+ MaxLength "255"
1125
+ AllowedPattern "[\\x20-\\x7E]*"
1126
+ ConstraintDescription "can contain only ASCII characters."
1127
+ end
1128
+ InstanceType do
1129
+ Description "WebServer EC2 instance type"
1130
+ Type "String"
1131
+ Default "m1.small"
1132
+ ConstraintDescription "must be a valid EC2 instance type."
1133
+ end
1134
+ SiteName do
1135
+ Default "My Site"
1136
+ Description "The name of the Drupal Site"
1137
+ Type "String"
1138
+ end
1139
+ SiteEMail do
1140
+ Description "EMail for site adminitrator"
1141
+ Type "String"
1142
+ end
1143
+ SiteAdmin do
1144
+ Description "The Drupal site admin account username"
1145
+ Type "String"
1146
+ MinLength "1"
1147
+ MaxLength "16"
1148
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
1149
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
1150
+ end
1151
+ SitePassword do
1152
+ NoEcho "true"
1153
+ Description "The Drupal site admin account password"
1154
+ Type "String"
1155
+ MinLength "1"
1156
+ MaxLength "41"
1157
+ AllowedPattern "[a-zA-Z0-9]*"
1158
+ ConstraintDescription "must contain only alphanumeric characters."
1159
+ end
1160
+ DBName do
1161
+ Default "drupaldb"
1162
+ Description "The Drupal database name"
1163
+ Type "String"
1164
+ MinLength "1"
1165
+ MaxLength "64"
1166
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
1167
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
1168
+ end
1169
+ DBUsername do
1170
+ Default "admin"
1171
+ NoEcho "true"
1172
+ Description "The Drupal database admin account username"
1173
+ Type "String"
1174
+ MinLength "1"
1175
+ MaxLength "16"
1176
+ AllowedPattern "[a-zA-Z][a-zA-Z0-9]*"
1177
+ ConstraintDescription "must begin with a letter and contain only alphanumeric characters."
1178
+ end
1179
+ DBPassword do
1180
+ Default "password"
1181
+ NoEcho "true"
1182
+ Description "The Drupal database admin account password"
1183
+ Type "String"
1184
+ MinLength "8"
1185
+ MaxLength "41"
1186
+ AllowedPattern "[a-zA-Z0-9]*"
1187
+ ConstraintDescription "must contain only alphanumeric characters."
1188
+ end
1189
+ DBClass do
1190
+ Default "db.m1.small"
1191
+ Description "Database instance class"
1192
+ Type "String"
1193
+ AllowedValues "db.m1.small", "db.m1.large", "db.m1.xlarge", "db.m2.xlarge", "db.m2.2xlarge", "db.m2.4xlarge"
1194
+ ConstraintDescription "must select a valid database instance type."
1195
+ end
1196
+ DBAllocatedStorage do
1197
+ Default "5"
1198
+ Description "The size of the database (Gb)"
1199
+ Type "Number"
1200
+ MinValue "5"
1201
+ MaxValue "1024"
1202
+ ConstraintDescription "must be between 5 and 1024Gb."
1203
+ end
1204
+ MultiAZDatabase do
1205
+ Default "true"
1206
+ Description "Create a multi-AZ MySQL Amazon RDS database instance"
1207
+ Type "String"
1208
+ AllowedValues "true", "false"
1209
+ ConstraintDescription "must be either true or false."
1210
+ end
1211
+ WebServerCapacity do
1212
+ Default "2"
1213
+ Description "The initial number of WebServer instances"
1214
+ Type "Number"
1215
+ MinValue "1"
1216
+ MaxValue "5"
1217
+ ConstraintDescription "must be between 1 and 5 EC2 instances."
1218
+ end
1219
+ SSHLocation do
1220
+ Description "The IP address range that can be used to SSH to the EC2 instances"
1221
+ Type "String"
1222
+ MinLength "9"
1223
+ MaxLength "18"
1224
+ Default "0.0.0.0/0"
1225
+ AllowedPattern "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})"
1226
+ ConstraintDescription "must be a valid IP CIDR range of the form x.x.x.x/x."
1227
+ end
1228
+ end
1229
+ Mappings do
1230
+ AWSInstanceType2Arch(
1231
+ {"t1.micro"=>{"Arch"=>"64"},
1232
+ "m1.small"=>{"Arch"=>"64"},
1233
+ "m1.medium"=>{"Arch"=>"64"},
1234
+ "m1.large"=>{"Arch"=>"64"},
1235
+ "m1.xlarge"=>{"Arch"=>"64"},
1236
+ "m2.xlarge"=>{"Arch"=>"64"},
1237
+ "m2.2xlarge"=>{"Arch"=>"64"},
1238
+ "m2.4xlarge"=>{"Arch"=>"64"},
1239
+ "m3.xlarge"=>{"Arch"=>"64"},
1240
+ "m3.2xlarge"=>{"Arch"=>"64"},
1241
+ "c1.medium"=>{"Arch"=>"64"},
1242
+ "c1.xlarge"=>{"Arch"=>"64"},
1243
+ "cc1.4xlarge"=>{"Arch"=>"64HVM"},
1244
+ "cc2.8xlarge"=>{"Arch"=>"64HVM"},
1245
+ "cg1.4xlarge"=>{"Arch"=>"64HVM"}})
1246
+ AWSRegionArch2AMI(
1247
+ {"us-east-1"=>
1248
+ {"32"=>"ami-a0cd60c9", "64"=>"ami-aecd60c7", "64HVM"=>"ami-a8cd60c1"},
1249
+ "us-west-2"=>
1250
+ {"32"=>"ami-46da5576", "64"=>"ami-48da5578", "64HVM"=>"NOT_YET_SUPPORTED"},
1251
+ "us-west-1"=>
1252
+ {"32"=>"ami-7d4c6938", "64"=>"ami-734c6936", "64HVM"=>"NOT_YET_SUPPORTED"},
1253
+ "eu-west-1"=>
1254
+ {"32"=>"ami-61555115", "64"=>"ami-6d555119", "64HVM"=>"ami-67555113"},
1255
+ "ap-southeast-1"=>
1256
+ {"32"=>"ami-220b4a70", "64"=>"ami-3c0b4a6e", "64HVM"=>"NOT_YET_SUPPORTED"},
1257
+ "ap-southeast-2"=>
1258
+ {"32"=>"ami-8f990eb5", "64"=>"ami-95990eaf", "64HVM"=>"NOT_YET_SUPPORTED"},
1259
+ "ap-northeast-1"=>
1260
+ {"32"=>"ami-2a19aa2b", "64"=>"ami-2819aa29", "64HVM"=>"NOT_YET_SUPPORTED"},
1261
+ "sa-east-1"=>
1262
+ {"32"=>"ami-f836e8e5", "64"=>"ami-fe36e8e3", "64HVM"=>"NOT_YET_SUPPORTED"}})
1263
+ end
1264
+ Resources do
1265
+ S3Bucket do
1266
+ Type "AWS::S3::Bucket"
1267
+ DeletionPolicy "Retain"
1268
+ end
1269
+ BucketPolicy do
1270
+ Type "AWS::S3::BucketPolicy"
1271
+ Properties do
1272
+ PolicyDocument do
1273
+ Version "2008-10-17"
1274
+ Id "UploadPolicy"
1275
+ Statement [
1276
+ _{
1277
+ Sid "EnableReadWrite"
1278
+ Action "s3:GetObject", "s3:PutObject", "s3:PutObjectACL"
1279
+ Effect "Allow"
1280
+ Resource do
1281
+ Fn__Join [
1282
+ "",
1283
+ ["arn:aws:s3:::", {"Ref"=>"S3Bucket"}, "/*"]
1284
+ ]
1285
+ end
1286
+ Principal do
1287
+ AWS do
1288
+ Fn__GetAtt "S3User", "Arn"
1289
+ end
1290
+ end
1291
+ }
1292
+ ]
1293
+ end
1294
+ Bucket do
1295
+ Ref "S3Bucket"
1296
+ end
1297
+ end
1298
+ end
1299
+ S3User do
1300
+ Type "AWS::IAM::User"
1301
+ Properties do
1302
+ Path "/"
1303
+ Policies [
1304
+ _{
1305
+ PolicyName "root"
1306
+ PolicyDocument do
1307
+ Statement [
1308
+ _{
1309
+ Effect "Allow"
1310
+ Action "s3:*"
1311
+ Resource "*"
1312
+ }
1313
+ ]
1314
+ end
1315
+ }
1316
+ ]
1317
+ end
1318
+ end
1319
+ S3Keys do
1320
+ Type "AWS::IAM::AccessKey"
1321
+ Properties do
1322
+ UserName do
1323
+ Ref "S3User"
1324
+ end
1325
+ end
1326
+ end
1327
+ ElasticLoadBalancer do
1328
+ Type "AWS::ElasticLoadBalancing::LoadBalancer"
1329
+ Metadata do
1330
+ Comment "Configure the Load Balancer with a simple health check and cookie-based stickiness"
1331
+ end
1332
+ Properties do
1333
+ AvailabilityZones do
1334
+ Fn__GetAZs ""
1335
+ end
1336
+ LBCookieStickinessPolicy [
1337
+ _{
1338
+ PolicyName "CookieBasedPolicy"
1339
+ CookieExpirationPeriod "30"
1340
+ }
1341
+ ]
1342
+ Listeners [
1343
+ _{
1344
+ LoadBalancerPort "80"
1345
+ InstancePort "80"
1346
+ Protocol "HTTP"
1347
+ PolicyNames ["CookieBasedPolicy"]
1348
+ }
1349
+ ]
1350
+ HealthCheck do
1351
+ Target "HTTP:80/"
1352
+ HealthyThreshold "2"
1353
+ UnhealthyThreshold "5"
1354
+ Interval "10"
1355
+ Timeout "5"
1356
+ end
1357
+ end
1358
+ end
1359
+ WebServerGroup do
1360
+ Type "AWS::AutoScaling::AutoScalingGroup"
1361
+ Properties do
1362
+ AvailabilityZones do
1363
+ Fn__GetAZs ""
1364
+ end
1365
+ LaunchConfigurationName do
1366
+ Ref "LaunchConfig"
1367
+ end
1368
+ MinSize "1"
1369
+ MaxSize "5"
1370
+ DesiredCapacity do
1371
+ Ref "WebServerCapacity"
1372
+ end
1373
+ LoadBalancerNames [
1374
+ _{
1375
+ Ref "ElasticLoadBalancer"
1376
+ }
1377
+ ]
1378
+ end
1379
+ end
1380
+ LaunchConfig do
1381
+ Type "AWS::AutoScaling::LaunchConfiguration"
1382
+ Metadata do
1383
+ AWS__CloudFormation__Init do
1384
+ config do
1385
+ packages do
1386
+ yum(
1387
+ {"httpd"=>[],
1388
+ "php"=>[],
1389
+ "php-mysql"=>[],
1390
+ "php-gd"=>[],
1391
+ "php-xml"=>[],
1392
+ "php-mbstring"=>[],
1393
+ "mysql"=>[],
1394
+ "gcc"=>[],
1395
+ "make"=>[],
1396
+ "libstdc++-devel"=>[],
1397
+ "gcc-c++"=>[],
1398
+ "fuse"=>[],
1399
+ "fuse-devel"=>[],
1400
+ "libcurl-devel"=>[],
1401
+ "libxml2-devel"=>[],
1402
+ "openssl-devel"=>[],
1403
+ "mailcap"=>[]})
1404
+ end
1405
+ sources do
1406
+ _path "/var/www/html", "http://ftp.drupal.org/files/projects/drupal-7.8.tar.gz"
1407
+ _path "/home/ec2-user", "http://ftp.drupal.org/files/projects/drush-7.x-4.5.tar.gz"
1408
+ _path "/home/ec2-user/s3fs", "http://s3fs.googlecode.com/files/s3fs-1.61.tar.gz"
1409
+ end
1410
+ files do
1411
+ _path("/etc/passwd-s3fs") do
1412
+ content do
1413
+ Fn__Join [
1414
+ "",
1415
+ [{"Ref"=>"S3Keys"}, ":", {"Fn::GetAtt"=>["S3Keys", "SecretAccessKey"]}, "\n"]
1416
+ ]
1417
+ end
1418
+ mode "000400"
1419
+ owner "root"
1420
+ group "root"
1421
+ end
1422
+ _path("/home/ec2-user/settings.php") do
1423
+ content do
1424
+ Fn__Join [
1425
+ "",
1426
+ ["<?php\n",
1427
+ "\n",
1428
+ "$databases = array (\n",
1429
+ " 'default' =>\n",
1430
+ " array (\n",
1431
+ " 'default' =>\n",
1432
+ " array (\n",
1433
+ " 'database' => '",
1434
+ {"Ref"=>"DBName"},
1435
+ "',\n",
1436
+ " 'username' => '",
1437
+ {"Ref"=>"DBUsername"},
1438
+ "',\n",
1439
+ " 'password' => '",
1440
+ {"Ref"=>"DBPassword"},
1441
+ "',\n",
1442
+ " 'host' => '",
1443
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Address"]},
1444
+ "',\n",
1445
+ " 'port' => '",
1446
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Port"]},
1447
+ "',\n",
1448
+ " 'driver' => 'mysql',\n",
1449
+ " 'prefix' => 'drupal_',\n",
1450
+ " ),\n",
1451
+ " ),\n",
1452
+ ");\n",
1453
+ "\n",
1454
+ "$update_free_access = FALSE;\n",
1455
+ "\n",
1456
+ "$drupal_hash_salt = '0c3R8noNALe3shsioQr5hK1dMHdwRfikLoSfqn0_xpA';\n",
1457
+ "\n",
1458
+ "ini_set('session.gc_probability', 1);\n",
1459
+ "ini_set('session.gc_divisor', 100);\n",
1460
+ "ini_set('session.gc_maxlifetime', 200000);\n",
1461
+ "ini_set('session.cookie_lifetime', 2000000);\n"]
1462
+ ]
1463
+ end
1464
+ mode "000400"
1465
+ owner "root"
1466
+ group "root"
1467
+ end
1468
+ end
1469
+ services do
1470
+ sysvinit do
1471
+ httpd do
1472
+ enabled "true"
1473
+ ensureRunning "true"
1474
+ end
1475
+ sendmail do
1476
+ enabled "false"
1477
+ ensureRunning "false"
1478
+ end
1479
+ end
1480
+ end
1481
+ end
1482
+ end
1483
+ end
1484
+ Properties do
1485
+ ImageId do
1486
+ Fn__FindInMap [
1487
+ "AWSRegionArch2AMI",
1488
+ _{
1489
+ Ref "AWS::Region"
1490
+ },
1491
+ _{
1492
+ Fn__FindInMap [
1493
+ "AWSInstanceType2Arch",
1494
+ _{
1495
+ Ref "InstanceType"
1496
+ },
1497
+ "Arch"
1498
+ ]
1499
+ }
1500
+ ]
1501
+ end
1502
+ InstanceType do
1503
+ Ref "InstanceType"
1504
+ end
1505
+ SecurityGroups [
1506
+ _{
1507
+ Ref "WebServerSecurityGroup"
1508
+ }
1509
+ ]
1510
+ KeyName do
1511
+ Ref "KeyName"
1512
+ end
1513
+ UserData do
1514
+ Fn__Base64 do
1515
+ Fn__Join [
1516
+ "",
1517
+ ["#!/bin/bash -v\n",
1518
+ "yum update -y aws-cfn-bootstrap\n",
1519
+ "# Helper function\n",
1520
+ "function error_exit\n",
1521
+ "{\n",
1522
+ " /opt/aws/bin/cfn-signal -e 1 -r \"$1\" '",
1523
+ {"Ref"=>"WaitHandle"},
1524
+ "'\n",
1525
+ " exit 1\n",
1526
+ "}\n",
1527
+ "# Install Apache Web Server, MySQL and Drupal\n",
1528
+ "/opt/aws/bin/cfn-init -s ",
1529
+ {"Ref"=>"AWS::StackId"},
1530
+ " -r LaunchConfig ",
1531
+ " --region ",
1532
+ {"Ref"=>"AWS::Region"},
1533
+ " || error_exit 'Failed to run cfn-init'\n",
1534
+ "# Install s3fs\n",
1535
+ "cd /home/ec2-user/s3fs/s3fs-1.61\n",
1536
+ "./configure --prefix=/usr\n",
1537
+ "make\n",
1538
+ "make install\n",
1539
+ "# Move the website files to the top level\n",
1540
+ "mv /var/www/html/drupal-7.8/* /var/www/html\n",
1541
+ "mv /var/www/html/drupal-7.8/.htaccess /var/www/html\n",
1542
+ "rm -Rf /var/www/html/drupal-7.8\n",
1543
+ "# Mount the S3 bucket\n",
1544
+ "mv /var/www/html/sites/default/files /var/www/html/sites/default/files_original\n",
1545
+ "mkdir -p /var/www/html/sites/default/files\n",
1546
+ "s3fs -o allow_other -o use_cache=/tmp ",
1547
+ {"Ref"=>"S3Bucket"},
1548
+ " /var/www/html/sites/default/files || error_exit 'Failed to mount the S3 bucket'\n",
1549
+ "echo `hostname` >> /var/www/html/sites/default/files/hosts\n",
1550
+ "# Make changes to Apache Web Server configuration\n",
1551
+ "sed -i 's/AllowOverride None/AllowOverride All/g' /etc/httpd/conf/httpd.conf\n",
1552
+ "service httpd restart\n",
1553
+ "# Only execute the site install if we are the first host up - otherwise we'll end up losing all the data\n",
1554
+ "read first < /var/www/html/sites/default/files/hosts\n",
1555
+ "if [ `hostname` = $first ]\n",
1556
+ "then\n",
1557
+ " # Create the site in Drupal\n",
1558
+ " cd /var/www/html\n",
1559
+ " ~ec2-user/drush/drush site-install standard --yes",
1560
+ " --site-name='",
1561
+ {"Ref"=>"SiteName"},
1562
+ "' --site-mail=",
1563
+ {"Ref"=>"SiteEMail"},
1564
+ " --account-name=",
1565
+ {"Ref"=>"SiteAdmin"},
1566
+ " --account-pass=",
1567
+ {"Ref"=>"SitePassword"},
1568
+ " --db-url=mysql://",
1569
+ {"Ref"=>"DBUsername"},
1570
+ ":",
1571
+ {"Ref"=>"DBPassword"},
1572
+ "@",
1573
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Address"]},
1574
+ ":",
1575
+ {"Fn::GetAtt"=>["DBInstance", "Endpoint.Port"]},
1576
+ "/",
1577
+ {"Ref"=>"DBName"},
1578
+ " --db-prefix=drupal_\n",
1579
+ " # use the S3 bucket for shared file storage\n",
1580
+ " cp -R sites/default/files_original/* sites/default/files\n",
1581
+ " cp -R sites/default/files_original/.htaccess sites/default/files\n",
1582
+ "else\n",
1583
+ " # Copy settings.php file since everything else is configured\n",
1584
+ " cp /home/ec2-user/settings.php /var/www/html/sites/default\n",
1585
+ "fi\n",
1586
+ "rm /home/ec2-user/settings.php\n",
1587
+ "# All is well so signal success\n",
1588
+ "/opt/aws/bin/cfn-signal -e 0 -r \"Drupal setup complete\" '",
1589
+ {"Ref"=>"WaitHandle"},
1590
+ "'\n"]
1591
+ ]
1592
+ end
1593
+ end
1594
+ end
1595
+ end
1596
+ WaitHandle do
1597
+ Type "AWS::CloudFormation::WaitConditionHandle"
1598
+ end
1599
+ WaitCondition do
1600
+ Type "AWS::CloudFormation::WaitCondition"
1601
+ DependsOn "WebServerGroup"
1602
+ Properties do
1603
+ Handle do
1604
+ Ref "WaitHandle"
1605
+ end
1606
+ Timeout "600"
1607
+ end
1608
+ end
1609
+ DBInstance do
1610
+ Type "AWS::RDS::DBInstance"
1611
+ Properties do
1612
+ DBName do
1613
+ Ref "DBName"
1614
+ end
1615
+ Engine "MySQL"
1616
+ MultiAZ do
1617
+ Ref "MultiAZDatabase"
1618
+ end
1619
+ MasterUsername do
1620
+ Ref "DBUsername"
1621
+ end
1622
+ DBInstanceClass do
1623
+ Ref "DBClass"
1624
+ end
1625
+ DBSecurityGroups [
1626
+ _{
1627
+ Ref "DBSecurityGroup"
1628
+ }
1629
+ ]
1630
+ AllocatedStorage do
1631
+ Ref "DBAllocatedStorage"
1632
+ end
1633
+ MasterUserPassword do
1634
+ Ref "DBPassword"
1635
+ end
1636
+ end
1637
+ end
1638
+ DBSecurityGroup do
1639
+ Type "AWS::RDS::DBSecurityGroup"
1640
+ Properties do
1641
+ DBSecurityGroupIngress do
1642
+ EC2SecurityGroupName do
1643
+ Ref "WebServerSecurityGroup"
1644
+ end
1645
+ end
1646
+ GroupDescription "Frontend Access"
1647
+ end
1648
+ end
1649
+ WebServerSecurityGroup do
1650
+ Type "AWS::EC2::SecurityGroup"
1651
+ Properties do
1652
+ GroupDescription "Enable HTTP access via port 80, locked down to requests from the load balancer only and SSH access"
1653
+ SecurityGroupIngress [
1654
+ _{
1655
+ IpProtocol "tcp"
1656
+ FromPort "80"
1657
+ ToPort "80"
1658
+ SourceSecurityGroupOwnerId do
1659
+ Fn__GetAtt "ElasticLoadBalancer", "SourceSecurityGroup.OwnerAlias"
1660
+ end
1661
+ SourceSecurityGroupName do
1662
+ Fn__GetAtt "ElasticLoadBalancer", "SourceSecurityGroup.GroupName"
1663
+ end
1664
+ },
1665
+ _{
1666
+ IpProtocol "tcp"
1667
+ FromPort "22"
1668
+ ToPort "22"
1669
+ CidrIp do
1670
+ Ref "SSHLocation"
1671
+ end
1672
+ }
1673
+ ]
1674
+ end
1675
+ end
1676
+ end
1677
+ Outputs do
1678
+ WebsiteURL do
1679
+ Value do
1680
+ Fn__Join [
1681
+ "",
1682
+ ["http://", {"Fn::GetAtt"=>["ElasticLoadBalancer", "DNSName"]}]
1683
+ ]
1684
+ end
1685
+ Description "Drupal Website"
1686
+ end
1687
+ end
1688
+ EOS
1689
+ end
508
1690
  end