diff --git a/.circleci/config.yml b/.circleci/config.yml index db5aa16..c345f9c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,19 +3,38 @@ version: 2.1 orbs: python: circleci/python@1.5.0 +commands: + destroy_environment: + steps: + - run: + name: Destroy environment + # ${CIRCLE_WORKFLOW_ID} is a Built-in environment variable + # ${CIRCLE_WORKFLOW_ID:0:5} takes the first 5 chars of the variable CIRCLE_CI_WORKFLOW_ID: + when: on_fail + command: | + aws cloudformation delete-stack --stack-name myStack-${CIRCLE_WORKFLOW_ID:0:7} + jobs: - create_infrastructure: + configure_infrastructure: docker: - - image: amazon/aws-cli + - image: python:3.7-alpine3.11 steps: - checkout + - add_ssh_keys: + fingerprints: [ "2a:2e:cc:14:0b:d6:f2:bd:33:0c:cf:34:29:7e:09:6e" ] - run: - name: Create Cloudformation Stack + name: Install dependencies (openssh) command: | - aws cloudformation deploy \ - --template-file ansible-ec2/template.yml \ - --stack-name myStack-${CIRCLE_WORKFLOW_ID:0:5} \ - --region us-east-1 + apk add --update openssh # Install openssh + - run: + name: Install Ansible + command: | + apk add --update ansible + - run: + name: Run Playbook and Configure server + command: | + ansible-playbook -i ansible-ec2/inventory.txt ansible-ec2/main-remote.yml + build-and-test: docker: - image: cimg/python:3.10.2 @@ -27,8 +46,112 @@ jobs: name: Run tests command: pytest + # Exercise - Rollback + create_infrastructure: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: + name: Create Cloudformation Stack + command: | + aws cloudformation deploy \ + --template-file ansible-ec2/template.yml \ + --stack-name myStack-${CIRCLE_WORKFLOW_ID:0:7} \ + --region us-east-1 + + smoke_test: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: + name: simulate error + command: | + return 1 + - destroy_environment +# URL="https://blog.udacity.com/" +# # Test if website exists +# if curl -s --head ${URL} +# then +# return 0 +# else +# return 1 +# fi + + create_and_deploy_front_end: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: + name: Execute bucket.yml - Create Cloudformation Stack + command: | + aws cloudformation deploy \ + --template-file ansible-ec2/bucket.yml \ + --stack-name stack-create-bucket-${CIRCLE_WORKFLOW_ID:0:7} \ + --parameter-overrides MyBucketName="mybucket-${CIRCLE_WORKFLOW_ID:0:7}" + # Uncomment the step below if yoou wish to upload all contents of the current directory to the S3 bucket + - run: aws s3 sync ansible-ec2/ s3://mybucket-${CIRCLE_WORKFLOW_ID:0:7} --delete + + # Executes the cloudfront.yml template that will modify the existing CloudFront Distribution, change its target from the old bucket to the new bucket - `mybucket-${CIRCLE_WORKFLOW_ID:0:7}`. + promote_to_production: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: + name: Execute cloudfront.yml + command: | + aws cloudformation deploy \ + --template-file ansible-ec2/cloudfront.yml \ + --stack-name production-distro \ + --parameter-overrides PipelineID="mybucket-${CIRCLE_WORKFLOW_ID:0:7}" + + # Fetch and save the pipeline ID (bucket ID) responsible for the last release. + get_last_deployment_id: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: yum install -y tar gzip + - run: + name: Fetch and save the old pipeline ID (bucket name) responsible for the last release. + command: | + aws cloudformation \ + list-exports --query "Exports[?Name==\`PipelineID\`].Value" \ + --no-paginate --output text > ~/textfile.txt + - persist_to_workspace: + root: ~/ + paths: + - textfile.txt + + # Destroy the previous production version's S3 bucket and CloudFormation stack. + clean_up_old_front_end: + docker: + - image: amazon/aws-cli + steps: + - checkout + - run: yum install -y tar gzip + - attach_workspace: + at: ~/ + - run: + name: Destroy the previous S3 bucket and CloudFormation stack. + # Use $OldBucketID environment variable or mybucket644752792305 below. + # Similarly, you can create and use $OldStackID environment variable in place of production-distro + command: | + export OldBucketID=$(cat ~/textfile.txt) + aws s3 rm "s3://${OldBucketID}" --recursive + workflows: sample: jobs: - - create_infrastructure - - build-and-test + - create_and_deploy_front_end + - promote_to_production: + requires: + - create_and_deploy_front_end + - get_last_deployment_id + - clean_up_old_front_end: + requires: + - get_last_deployment_id + - promote_to_production diff --git a/.gitignore b/.gitignore index 99debc8..9d60a55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ venv .idea/ *.pyc +*.DS_Store +.DS_Store \ No newline at end of file diff --git a/ansible-ec2/Project-udacity.pem b/ansible-ec2/Project-udacity.pem deleted file mode 100644 index b3c79f1..0000000 --- a/ansible-ec2/Project-udacity.pem +++ /dev/null @@ -1,27 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIIEpAIBAAKCAQEAoiPDum+RIPGxAnrTSGI1W04wg8Q+Td8IdnyJEn7ElINnANXN -FgF799pr0OjyMoK3idfU770544SHTXwI+/C4PZOtv46kKLrPuA8BfUi2tTJWFQQD -s1f9E9UHOlMs1NBHwUjAvtAkGpl00ruuhRXBmtSgkgwhXYfjejYVDrIoKLg56BI7 -PCqQHoje3M+IJxhtx4qZNZEc+pzOb6N6cg07MaXAqwStKQOcUQ9QbBzMqpchnVcE -YKc2210J9E8LY59bWD/63wjUQS//2WvGA05vW/J39tOR9955yLh/fuTqy7rMpfKj -rMICQRLyqWtVJELMwVjgxNKq0Ii4t3T2q0xptwIDAQABAoIBAFAJdZHvhuWLSUSf -GvLtP8d9lmdFFThdc5EBsqxFlYZ2Qv9fiuhk/SwBTx2GECCs9CsANuXNM+lCv4OZ -SdoMHvaOksMvh4tvhCAokCSnI0HYwjOHksgSFCSZEQNSkZvP4MvhvPu0RU44GDn6 -WZDqh3KFqWnOwR2peboXPlfNzBMk6nlKAppJ0vRbVlE4PNGqtXEgZ9iLt/m0bRz8 -telUfkOIjNWNI7yy3tKGYsBMTQYg9WyzOUFEqrYHOIdq8o+6ERiHWPUoOl5d3mPr -Ll0GlHCzDPr5N5UEIbv758JeVk68u73b0rfFgdiCy0beWfsUjRRDUhbeWEyC6xkE -8nh0LmECgYEA6222o7KtYgWS0B5u9Kkwez6XcRuJOyAKEZrLG39NSiPWepTt8toU -huUD+AKuCJ0WQYOuRCClqjiAY0SwvRIz1w0jDvRq7gZUtsciHcavJGPYtIfHmSQd -22t9wMzGXytWMF0GPFfkD7LAi20c3ypGynSegasHV6aUqi4QBbNOJ/ECgYEAsE6o -QYKh/YhieJYULokzsRQIkerbEM6xOoeEzutzWlrOfMoZN9g7KDZ4ZR95uRr60D6w -Fj0obVV+vaEWAlSEWYyrm8qTJCFTo6XLDz3HK/SBEJxtay3Sn4TCPqRlpenh8aPP -XZPm2lVfmKPuzKFsbjq24wtDHRQKO5A1C/UdlCcCgYEAjbhGuHYHrzkBrqyTSE5M -s/PywBC+ZEweI4jV+SCByz6Vjsb2Ejm7H5Te9b3PO7osOpXlInewoi5PAvLHnZlG -gY8T6p2xfMVs23Y2EEyZA8PjIJGX0pUOMBad5aCfTYzN3mExLsQNsnF9PLEbLy/I -23imLhJhYh8R4PvHg1bzllECgYEArkNAyWeeR6NreTcWAZ05S5i6k8en+afiwzA5 -0/AjVzaUDAISBQGkDy4vt/vxa0XAjN65W3HdqJutpy82Ot1g58ZDxLvozfhm3ES+ -PXVZjReiDlIfUKW9HlCxUgtaMTDIU/gOuba7oihqUcwO95HCQ/2i0S1Li81IA/GY -jRYcw1cCgYBJVhdq0hGFiPhlXRuWMltR5hs6AopOq/5QC9RzSU2alaC9tkWkiKD9 -+ncnCBRhAvRhcmTcuGA+a5F1oV4yH5/xlIQxMikb0GGWvlCC9Kp9qveNkzT3whIm -AG0gIOuCZXvu4CEllNw9mAReC5EMbw1y73QtnJgtR9Olp4XTo/0UHQ== ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/ansible-ec2/aws cmds b/ansible-ec2/aws cmds new file mode 100644 index 0000000..f2f2151 --- /dev/null +++ b/ansible-ec2/aws cmds @@ -0,0 +1,6 @@ +aws cloudformation deploy \ +--template-file cloudfront.yml \ +--stack-name production-distro \ +--parameter-overrides PipelineID="roboticsbucket" \ # Name of the S3 bucket you created manually. +--tags project=udapeople + diff --git a/ansible-ec2/bucket.yml b/ansible-ec2/bucket.yml new file mode 100644 index 0000000..9660c01 --- /dev/null +++ b/ansible-ec2/bucket.yml @@ -0,0 +1,26 @@ +Parameters: + # New Bucket name + MyBucketName: + Description: Existing Bucket name + Type: String + +Resources: + WebsiteBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: !Sub "${MyBucketName}" + AccessControl: PublicRead + WebsiteConfiguration: + IndexDocument: index.html + ErrorDocument: error.html + WebsiteBucketPolicy: + Type: AWS::S3::BucketPolicy + Properties: + Bucket: !Ref 'WebsiteBucket' + PolicyDocument: + Statement: + - Sid: PublicReadForGetBucketObjects + Effect: Allow + Principal: '*' + Action: s3:GetObject + Resource: !Join ['', ['arn:aws:s3:::', !Ref 'WebsiteBucket', /*]] \ No newline at end of file diff --git a/ansible-ec2/cloudfront.yml b/ansible-ec2/cloudfront.yml new file mode 100644 index 0000000..fca5445 --- /dev/null +++ b/ansible-ec2/cloudfront.yml @@ -0,0 +1,35 @@ +Parameters: + # Existing Bucket name + PipelineID: + Description: Existing Bucket name + Type: String + +Resources: + CloudFrontOriginAccessIdentity: + Type: "AWS::CloudFront::CloudFrontOriginAccessIdentity" + Properties: + CloudFrontOriginAccessIdentityConfig: + Comment: Origin Access Identity for Serverless Static Website + + WebpageCDN: + Type: AWS::CloudFront::Distribution + Properties: + DistributionConfig: + Origins: + - DomainName: !Sub "${PipelineID}.s3.amazonaws.com" + Id: webpage + S3OriginConfig: + OriginAccessIdentity: !Sub "origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}" + Enabled: True + DefaultRootObject: index.html + DefaultCacheBehavior: + ForwardedValues: + QueryString: False + TargetOriginId: webpage + ViewerProtocolPolicy: allow-all + +Outputs: + PipelineID: + Value: !Sub ${PipelineID} + Export: + Name: PipelineID \ No newline at end of file diff --git a/ansible-ec2/inventory b/ansible-ec2/inventory deleted file mode 100644 index 7ce733e..0000000 --- a/ansible-ec2/inventory +++ /dev/null @@ -1,2 +0,0 @@ -[all] -3.89.252.120 diff --git a/ansible-ec2/inventory.txt b/ansible-ec2/inventory.txt new file mode 100644 index 0000000..5dc11c1 --- /dev/null +++ b/ansible-ec2/inventory.txt @@ -0,0 +1,2 @@ +[all] +ec2-54-161-67-165.compute-1.amazonaws.com diff --git a/ansible-ec2/udacity.pem b/ansible-ec2/udacity.pem new file mode 100644 index 0000000..fd46709 --- /dev/null +++ b/ansible-ec2/udacity.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAlqAxJfddGLQMaSd4Z1JSaZ3KWB6hD1kl+2L1XXeHljHFOQcM +XQN91OYFf35oNbF9tpyl5rXQLqFOmpF4A304dbEn55KYyJCTm54cASAxXbeH03Iy +Zrv39eUrIi4KbsCQ32j1YImV1d5znMXhM11KbKORiaxRdZPuL+NcPJba3OHrqxIH +TfQ9sazU6YjWiXuBvN1gU2Z/lQWA79E7aDylaNTL9JxXBliAfELc73t76S+Dwal0 +jPkfQdzAmEWUOeJBMqEyuS7EBQeavKH6nJfIRj/OYztCWfw/LE31b3Y8cue1dT7j +euwhfPofHc7Gpn8NJojkmhfAhzfO7BRTtmePNwIDAQABAoIBAHYK1HmMgcj6UT+X +TySpvyxGHG0yk8YTd1CrHN9C7V8nYghvHaFHOzW9jlF8Hu71Si/yU5Gaqqvgfllj +50nUuIqDa2Jv4IxNwWATaJ75O7bWPfvXYuhgJtLt5f/DVSm2f9KVzrb5HBOfYbta +2EIIumqpRUU/Zhde9ytQYtiY4Kx4qX2MpDhWSevP5raKfljLWn6CKpB//3q5/xFu +L8NJuIDlZSNbP1r5D4z6FlDq3OJ/d8YNFzbNCnRTD5cML35wzKrNbbQqyDBJeo4D +dnM4ZWbqP6nFhl2kslUJtblxiY5iG+CRieiEHnZJz0lpBuJKAtM5vaG2KsP5qcaa +o1oefAECgYEA5KWpXiI9eETcFYBDSeLo34Mb0A7O13HI3chBqhoLEyEFaYRu0gES +L+Tt7c2bHlpMSGvP4Eq5TQlr8A6ya0nrI6j/WeQcYVI8QM8mvS+MwyyY5RgU0d3c +ujbE5x3UtQSnUoWsEr3GckjxI45mPSPD7QanJ0CAg8iopmWq+glEP8cCgYEAqKUe +e9j1w1dQQbEfAWOxexk8A/kYdFNwWMUVEIAmbWH6lFGNNP/jsL2QaWpIxSrl+Muy +g8+L5axATn5FczZN1DBXPNTzJDLJOUWyFhNURJXTYSORYm7UUIOrxgyH1ZY6bwtr +XcSS6H4AqSldnB2uqKvw98ANNMxp7QeV9gs8FRECgYARUKZR1Z/4EqbkDfGKj994 +xbH+gJCTai9+9CJc4loCWdbSFdBaoPAipmCKSK69jrMGLPvyDVaZCeSdqk9Cprdi +3PJxeT/Y8uRTOBzD6Ozs/tyZRMiW2AlWJL2mjvDDwJV3P143kR2NHA7+1VLSwHme +4okYBN92m2SCLWLUSo1bkwKBgCIoX4ZCKXUJSE4l69vCL355W/iKCXP2OnkgYeXX +rvDUuYY1Bl7HvXxcyNUxG9AjojTEPUIJVZKNUvETDkoJo7XonKLLlvur9anN/gYO +oDDMD+ZK5/WB8SrloHMasqCGLwuyympRmFfSvZuFr1ohgPDU8pebpJEfHg1OTgdp +ux+hAoGAH5jD4kI4BwMFgHTCvhstNjctWbPkr3bjdTnl2jDrsBUQpPhRAnCyXcBM +U8MQI272GWTR4pRjPemQYbf4mbRoxb1toh1+BIsoHdX87o5Xk7qWd3tYNdAXSZPK +38q3ZZIf/pMjhNYVnrEcJNgeKXYXA9vRYmoE76SwRAm8fguPafo= +-----END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/ansible.cfg b/ansible.cfg new file mode 100644 index 0000000..d313d1b --- /dev/null +++ b/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +host_key_checking = false \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..1314601 --- /dev/null +++ b/index.html @@ -0,0 +1,10 @@ + + + + Version 1 + + + +

Hello World - version 1

+ +