dslh 0.1.8 → 0.1.9

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.
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