diff --git a/ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml b/ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml new file mode 100644 index 0000000000..a3f8cd9549 --- /dev/null +++ b/ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml @@ -0,0 +1,22 @@ +plugin: aws_ec2 +regions: + - "us-east-1" +filters: + tag:app-stack-name: APP_STACK_NAME + tag:environment: dev +keyed_groups: + - key: tags['app-stack-name'] + prefix: 'app_stack_' + separator: '' + - key: tags['swarm-role'] + prefix: 'role_' + separator: '' + - key: tags['environment'] + prefix: 'env_' + separator: '' + - key: tags['server'] + separator: '' +hostnames: + - "private-ip-address" +compose: + ansible_user: "'ec2-user'" \ No newline at end of file diff --git a/ansible/inventory/dev_stack_swarm_grand_master_aws_ec2.yaml b/ansible/inventory/dev_stack_swarm_grand_master_aws_ec2.yaml new file mode 100644 index 0000000000..b1569ff1d9 --- /dev/null +++ b/ansible/inventory/dev_stack_swarm_grand_master_aws_ec2.yaml @@ -0,0 +1,11 @@ +plugin: aws_ec2 +regions: + - "us-east-1" +filters: + tag:app-stack-name: APP_STACK_NAME + tag:environment: dev + tag:swarm-role: grand-master +hostnames: + - "private-ip-address" +compose: + ansible_user: "'ec2-user'" \ No newline at end of file diff --git a/ansible/inventory/dev_stack_swarm_managers_aws_ec2.yaml b/ansible/inventory/dev_stack_swarm_managers_aws_ec2.yaml new file mode 100644 index 0000000000..e9647b593b --- /dev/null +++ b/ansible/inventory/dev_stack_swarm_managers_aws_ec2.yaml @@ -0,0 +1,11 @@ +plugin: aws_ec2 +regions: + - "us-east-1" +filters: + tag:app-stack-name: APP_STACK_NAME + tag:environment: dev + tag:swarm-role: manager +hostnames: + - "private-ip-address" +compose: + ansible_user: "'ec2-user'" \ No newline at end of file diff --git a/ansible/inventory/dev_stack_swarm_workers_aws_ec2.yaml b/ansible/inventory/dev_stack_swarm_workers_aws_ec2.yaml new file mode 100644 index 0000000000..f702f7ad93 --- /dev/null +++ b/ansible/inventory/dev_stack_swarm_workers_aws_ec2.yaml @@ -0,0 +1,11 @@ +plugin: aws_ec2 +regions: + - "us-east-1" +filters: + tag:app-stack-name: APP_STACK_NAME + tag:environment: dev + tag:swarm-role: worker +hostnames: + - "private-ip-address" +compose: + ansible_user: "'ec2-user'" \ No newline at end of file diff --git a/ansible/inventory/hosts.ini b/ansible/inventory/hosts.ini new file mode 100644 index 0000000000..cd3534ffd5 --- /dev/null +++ b/ansible/inventory/hosts.ini @@ -0,0 +1,5 @@ +172.31.18.79 ansible_user=ec2-user +172.31.17.104 ansible_user=ec2-user +172.31.82.199 ansible_user=ec2-user +172.31.27.10 ansible_user=ec2-user +172.31.83.29 ansible_user=ec2-user \ No newline at end of file diff --git a/ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml b/ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml new file mode 100644 index 0000000000..ea26604c19 --- /dev/null +++ b/ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml @@ -0,0 +1,22 @@ +plugin: aws_ec2 +regions: + - "us-east-1" +filters: + tag:app-stack-name: APP_STACK_NAME + tag:environment: qa +keyed_groups: + - key: tags['app-stack-name'] + prefix: 'app_stack_' + separator: '' + - key: tags['swarm-role'] + prefix: 'role_' + separator: '' + - key: tags['environment'] + prefix: 'env_' + separator: '' + - key: tags['server'] + separator: '' +hostnames: + - "private-ip-address" +compose: + ansible_user: "'ec2-user'" \ No newline at end of file diff --git a/ansible/playbooks/pb_deploy_app_on_docker_swarm.yaml b/ansible/playbooks/pb_deploy_app_on_docker_swarm.yaml new file mode 100644 index 0000000000..fe81737bbc --- /dev/null +++ b/ansible/playbooks/pb_deploy_app_on_docker_swarm.yaml @@ -0,0 +1,14 @@ +--- +- hosts: role_grand_master + tasks: + - name: Copy docker compose file to grand master + copy: + src: "{{ workspace }}/docker-compose-swarm-dev-tagged.yml" + dest: /home/ec2-user/docker-compose-swarm-dev-tagged.yml + - name: get login credentials for ecr + shell: "export PATH=$PATH:/usr/local/bin/ && aws ecr get-login-password --region {{ aws_region }} | docker login --username AWS --password-stdin {{ ecr_registry }}" + register: output + - name: deploy the app stack on swarm + shell: "docker stack deploy --with-registry-auth -c /home/ec2-user/docker-compose-swarm-dev-tagged.yml {{ app_name }}" + register: output + - debug: msg="{{ output.stdout }}" \ No newline at end of file diff --git a/ansible/playbooks/pb_deploy_app_on_qa_environment.yaml b/ansible/playbooks/pb_deploy_app_on_qa_environment.yaml new file mode 100644 index 0000000000..c1a1711de2 --- /dev/null +++ b/ansible/playbooks/pb_deploy_app_on_qa_environment.yaml @@ -0,0 +1,14 @@ +--- +- hosts: role_grand_master + tasks: + - name: Copy docker compose file to grand master + copy: + src: "{{ workspace }}/docker-compose-swarm-qa-tagged.yml" + dest: /home/ec2-user/docker-compose-swarm-qa-tagged.yml + - name: get login credentials for ecr + shell: "export PATH=$PATH:/usr/local/bin/ && aws ecr get-login-password --region {{ aws_region }} | docker login --username AWS --password-stdin {{ ecr_registry }}" + register: output + - name: deploy the app stack on swarm + shell: "docker stack deploy --with-registry-auth -c /home/ec2-user/docker-compose-swarm-qa-tagged.yml {{ app_name }}" + register: output + - debug: msg="{{ output.stdout }}" \ No newline at end of file diff --git a/ansible/playbooks/pb_initialize_docker_swarm.yaml b/ansible/playbooks/pb_initialize_docker_swarm.yaml new file mode 100644 index 0000000000..e1a9c473fc --- /dev/null +++ b/ansible/playbooks/pb_initialize_docker_swarm.yaml @@ -0,0 +1,13 @@ +--- +- hosts: role_grand_master + tasks: + - name: initialize docker swarm + shell: docker swarm init + - name: run the visualizer app for docker swarm + shell: | + docker service create \ + --name=viz \ + --publish=8088:8080/tcp \ + --constraint=node.role==manager \ + --mount=type=bind,src=/var/run/docker.sock,dst=/var/run/docker.sock \ + dockersamples/visualizer \ No newline at end of file diff --git a/ansible/playbooks/pb_join_docker_swarm_managers.yaml b/ansible/playbooks/pb_join_docker_swarm_managers.yaml new file mode 100644 index 0000000000..b9ac69c7c3 --- /dev/null +++ b/ansible/playbooks/pb_join_docker_swarm_managers.yaml @@ -0,0 +1,17 @@ +--- +- hosts: role_grand_master + tasks: + - name: Get swarm join-token for managers + shell: docker swarm join-token manager | grep -i 'docker' + register: join_command_for_managers + - debug: msg='{{ join_command_for_managers.stdout.strip() }}' + - name: register grand_master with variable + add_host: + name: "grand_master" + manager_join: "{{ join_command_for_managers.stdout.strip() }}" +- hosts: role_manager + tasks: + - name: Join managers to swarm + shell: "{{ hostvars['grand_master']['manager_join'] }}" + register: result_of_joining + - debug: msg='{{ result_of_joining.stdout }}' \ No newline at end of file diff --git a/ansible/playbooks/pb_join_docker_swarm_workers.yaml b/ansible/playbooks/pb_join_docker_swarm_workers.yaml new file mode 100644 index 0000000000..19df5e03f7 --- /dev/null +++ b/ansible/playbooks/pb_join_docker_swarm_workers.yaml @@ -0,0 +1,17 @@ +--- +- hosts: role_grand_master + tasks: + - name: Get swarm join-token for workers + shell: docker swarm join-token worker | grep -i 'docker' + register: join_command_for_workers + - debug: msg='{{ join_command_for_workers.stdout.strip() }}' + - name: register grand_master with variable + add_host: + name: "grand_master" + worker_join: "{{ join_command_for_workers.stdout.strip() }}" +- hosts: role_worker + tasks: + - name: Join workers to swarm + shell: "{{ hostvars['grand_master']['worker_join'] }}" + register: result_of_joining + - debug: msg='{{ result_of_joining.stdout }}' \ No newline at end of file diff --git a/ansible/playbooks/pb_run_dummy_selenium_job.yaml b/ansible/playbooks/pb_run_dummy_selenium_job.yaml new file mode 100644 index 0000000000..9585026caa --- /dev/null +++ b/ansible/playbooks/pb_run_dummy_selenium_job.yaml @@ -0,0 +1,10 @@ +--- +- hosts: all + tasks: + - name: run dummy selenium job + shell: "docker run --rm -v {{ workspace }}:{{ workspace }} -w {{ workspace }} callahanclarus/selenium-py-chrome:latest python {{ item }}" + with_fileglob: "{{ workspace }}/selenium-jobs/dummy*.py" + register: output + - name: show results + debug: msg="{{ item.stdout }}" + with_items: "{{ output.results }}" \ No newline at end of file diff --git a/ansible/playbooks/pb_run_selenium_jobs.yaml b/ansible/playbooks/pb_run_selenium_jobs.yaml new file mode 100644 index 0000000000..3c76d89025 --- /dev/null +++ b/ansible/playbooks/pb_run_selenium_jobs.yaml @@ -0,0 +1,10 @@ +--- +- hosts: all + tasks: + - name: run all selenium jobs + shell: "docker run --rm --env MASTER_PUBLIC_IP={{ master_public_ip }} -v {{ workspace }}:{{ workspace }} -w {{ workspace }} callahanclarus/selenium-py-chrome:latest python {{ item }}" + register: output + with_fileglob: "{{ workspace }}/selenium-jobs/test*.py" + - name: show results + debug: msg="{{ item.stdout }}" + with_items: "{{ output.results }}" \ No newline at end of file diff --git a/ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml b/ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml new file mode 100644 index 0000000000..d4d401cd1c --- /dev/null +++ b/ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml @@ -0,0 +1,53 @@ +--- +- hosts: all + tasks: + - name: update os + yum: + name: '*' + state: present + - name: install docker + command: amazon-linux-extras install docker=latest -y + - name: start docker + service: + name: docker + state: started + enabled: yes + - name: add ec2-user to docker group + shell: "usermod -a -G docker ec2-user" + - name: Install Docker Compose (if configured). + get_url: + url: https://github.com/docker/compose/releases/download/1.26.2/docker-compose-Linux-x86_64 + dest: /usr/local/bin/docker-compose + mode: 0755 + - name: uninstall aws cli v1 + file: + path: /bin/aws + state: absent + - name: Download awscliv2 installer + unarchive: + src: https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip + dest: /tmp + remote_src: yes + creates: /tmp/aws + mode: 0755 + - name: Run the installer. + command: + args: + cmd: "/tmp/aws/install" + creates: /usr/local/bin/aws + - name: install ecr credential helper + yum: + name: amazon-ecr-credential-helper + state: present + - name: Create folder for config file of ecr cred helper + file: + path: /home/ec2-user/.docker + state: directory + owner: "ec2-user" + mode: "g+rwx" + - name: create config file with content for ecr creds + copy: + content: '{"credsStore":"ecr-login"}' + dest: /home/ec2-user/.docker/config.json + owner: "ec2-user" + mode: "g+rwx" \ No newline at end of file diff --git a/ansible/scripts/deploy_app_on_docker_swarm.sh b/ansible/scripts/deploy_app_on_docker_swarm.sh new file mode 100644 index 0000000000..d36c706bfc --- /dev/null +++ b/ansible/scripts/deploy_app_on_docker_swarm.sh @@ -0,0 +1,4 @@ +PATH="$PATH:/usr/local/bin" +APP_NAME="petclinic" +envsubst < docker-compose-swarm-dev.yml > docker-compose-swarm-dev-tagged.yml +ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b --extra-vars "workspace=${WORKSPACE} app_name=${APP_NAME} aws_region=${AWS_REGION} ecr_registry=${ECR_REGISTRY}" ./ansible/playbooks/pb_deploy_app_on_docker_swarm.yaml \ No newline at end of file diff --git a/ansible/scripts/deploy_app_on_qa_environment.sh b/ansible/scripts/deploy_app_on_qa_environment.sh new file mode 100644 index 0000000000..377b897fdb --- /dev/null +++ b/ansible/scripts/deploy_app_on_qa_environment.sh @@ -0,0 +1,5 @@ +PATH="$PATH:/usr/local/bin" +APP_NAME="petclinic" +sed -i "s/APP_STACK_NAME/${APP_STACK_NAME}/" ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml +envsubst < docker-compose-swarm-qa.yml > docker-compose-swarm-qa-tagged.yml +ansible-playbook -i ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml -b --extra-vars "workspace=${WORKSPACE} app_name=${APP_NAME} aws_region=${AWS_REGION} ecr_registry=${ECR_REGISTRY}" ./ansible/playbooks/pb_deploy_app_on_qa_environment.yaml \ No newline at end of file diff --git a/ansible/scripts/run_dummy_selenium_job.sh b/ansible/scripts/run_dummy_selenium_job.sh new file mode 100644 index 0000000000..4e5d10d053 --- /dev/null +++ b/ansible/scripts/run_dummy_selenium_job.sh @@ -0,0 +1,2 @@ +PATH="$PATH:/usr/local/bin" +ansible-playbook --connection=local --inventory 127.0.0.1, --extra-vars "workspace=${WORKSPACE}" ./ansible/playbooks/pb_run_dummy_selenium_job.yaml \ No newline at end of file diff --git a/ansible/scripts/run_selenium_jobs.sh b/ansible/scripts/run_selenium_jobs.sh new file mode 100644 index 0000000000..0306d867a0 --- /dev/null +++ b/ansible/scripts/run_selenium_jobs.sh @@ -0,0 +1,3 @@ +PATH="$PATH:/usr/local/bin" +ansible-playbook -vvv --connection=local --inventory 127.0.0.1, +--extra-vars "workspace=${WORKSPACE} master_public_ip=${GRAND_MASTER_PUBLIC_IP}" ./ansible/playbooks/pb_run_selenium_jobs.yaml diff --git a/build-dev-docker-images.sh b/build-dev-docker-images.sh new file mode 100644 index 0000000000..1c5441a219 --- /dev/null +++ b/build-dev-docker-images.sh @@ -0,0 +1,12 @@ +# build-dev-docker-images +./mvnw clean package +docker build --force-rm -t "petclinic-admin-server:dev" ./spring-petclinic-admin-server +docker build --force-rm -t "petclinic-api-gateway:dev" ./spring-petclinic-api-gateway +docker build --force-rm -t "petclinic-config-server:dev" ./spring-petclinic-config-server +docker build --force-rm -t "petclinic-customers-service:dev" ./spring-petclinic-customers-service +docker build --force-rm -t "petclinic-discovery-server:dev" ./spring-petclinic-discovery-server +docker build --force-rm -t "petclinic-hystrix-dashboard:dev" ./spring-petclinic-hystrix-dashboard +docker build --force-rm -t "petclinic-vets-service:dev" ./spring-petclinic-vets-service +docker build --force-rm -t "petclinic-visits-service:dev" ./spring-petclinic-visits-service +docker build --force-rm -t "petclinic-prometheus-server:dev" ./docker/prometheus +docker build --force-rm -t "petclinic-grafana-server:dev" ./docker/grafana \ No newline at end of file diff --git a/docker-compose-local.yml b/docker-compose-local.yml new file mode 100644 index 0000000000..195b20637c --- /dev/null +++ b/docker-compose-local.yml @@ -0,0 +1,97 @@ +version: '2' +services: + config-server: + image: petclinic-config-server:dev + container_name: config-server + mem_limit: 512M + ports: + - 8888:8888 + discovery-server: + image: petclinic-discovery-server:dev + container_name: discovery-server + mem_limit: 512M + ports: + - 8761:8761 + depends_on: + - config-server + entrypoint: ["./dockerize", "-wait=tcp://config-server:8888", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + customers-service: + image: petclinic-customers-service:dev + container_name: customers-service + mem_limit: 512M + ports: + - 8081:8081 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + visits-service: + image: petclinic-visits-service:dev + container_name: visits-service + mem_limit: 512M + ports: + - 8082:8082 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + vets-service: + image: petclinic-vets-service:dev + container_name: vets-service + mem_limit: 512M + ports: + - 8083:8083 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + api-gateway: + image: petclinic-api-gateway:dev + container_name: api-gateway + mem_limit: 512M + ports: + - 8080:8080 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + admin-server: + image: petclinic-admin-server:dev + container_name: admin-server + mem_limit: 512M + ports: + - 9090:9090 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + hystrix-dashboard: + image: petclinic-hystrix-dashboard:dev + container_name: hystrix-dashboard + mem_limit: 512M + ports: + - 7979:7979 + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize", "-wait=tcp://discovery-server:8761", "-timeout=60s", "--", "java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar" ] + tracing-server: + image: openzipkin/zipkin + container_name: tracing-server + mem_limit: 512M + environment: + - JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom + ports: + - 9411:9411 + grafana-server: + image: petclinic-grafana-server:dev + container_name: grafana-server + mem_limit: 256M + ports: + - 3000:3000 + prometheus-server: + image: petclinic-prometheus-server:dev + container_name: prometheus-server + mem_limit: 256M + ports: + - 9091:9090 \ No newline at end of file diff --git a/docker-compose-swarm-dev.yml b/docker-compose-swarm-dev.yml new file mode 100644 index 0000000000..4ccb0f2f25 --- /dev/null +++ b/docker-compose-swarm-dev.yml @@ -0,0 +1,125 @@ +version: '3.8' +services: + config-server: + image: "${IMAGE_TAG_CONFIG_SERVER}" + networks: + - clarusnet + ports: + - 8888:8888 + discovery-server: + image: "${IMAGE_TAG_DISCOVERY_SERVER}" + depends_on: + - config-server + entrypoint: ["./dockerize","-wait=tcp://config-server:8888","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8761:8761 + customers-service: + image: "${IMAGE_TAG_CUSTOMERS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8081:8081 + visits-service: + image: "${IMAGE_TAG_VISITS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8082:8082 + vets-service: + image: "${IMAGE_TAG_VETS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8083:8083 + api-gateway: + image: "${IMAGE_TAG_API_GATEWAY}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8080:8080 + tracing-server: + image: openzipkin/zipkin + environment: + - JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom + networks: + - clarusnet + ports: + - 9411:9411 + admin-server: + image: "${IMAGE_TAG_ADMIN_SERVER}" + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 9090:9090 + hystrix-dashboard: + image: "${IMAGE_TAG_HYSTRIX_DASHBOARD}" + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 7979:7979 + ## Grafana / Prometheus + grafana-server: + image: "${IMAGE_TAG_GRAFANA_SERVICE}" + networks: + - clarusnet + ports: + - 3000:3000 + prometheus-server: + image: "${IMAGE_TAG_PROMETHEUS_SERVICE}" + networks: + - clarusnet + ports: + - 9091:9090 +networks: + clarusnet: + driver: overlay \ No newline at end of file diff --git a/docker-compose-swarm-qa.yml b/docker-compose-swarm-qa.yml new file mode 100644 index 0000000000..64211364a8 --- /dev/null +++ b/docker-compose-swarm-qa.yml @@ -0,0 +1,125 @@ +version: '3.8' +services: + config-server: + image: "${IMAGE_TAG_CONFIG_SERVER}" + networks: + - clarusnet + ports: + - 8888:8888 + discovery-server: + image: "${IMAGE_TAG_DISCOVERY_SERVER}" + depends_on: + - config-server + entrypoint: ["./dockerize","-wait=tcp://config-server:8888","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8761:8761 + customers-service: + image: "${IMAGE_TAG_CUSTOMERS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8081:8081 + visits-service: + image: "${IMAGE_TAG_VISITS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8082:8082 + vets-service: + image: "${IMAGE_TAG_VETS_SERVICE}" + deploy: + replicas: 3 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8083:8083 + api-gateway: + image: "${IMAGE_TAG_API_GATEWAY}" + deploy: + replicas: 5 + update_config: + parallelism: 2 + delay: 5s + order: start-first + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 8080:8080 + tracing-server: + image: openzipkin/zipkin + environment: + - JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom + networks: + - clarusnet + ports: + - 9411:9411 + admin-server: + image: "${IMAGE_TAG_ADMIN_SERVER}" + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 9090:9090 + hystrix-dashboard: + image: "${IMAGE_TAG_HYSTRIX_DASHBOARD}" + depends_on: + - config-server + - discovery-server + entrypoint: ["./dockerize","-wait=tcp://discovery-server:8761","-timeout=60s","--","java", "-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"] + networks: + - clarusnet + ports: + - 7979:7979 + ## Grafana / Prometheus + grafana-server: + image: "${IMAGE_TAG_GRAFANA_SERVICE}" + networks: + - clarusnet + ports: + - 3000:3000 + prometheus-server: + image: "${IMAGE_TAG_PROMETHEUS_SERVICE}" + networks: + - clarusnet + ports: + - 9091:9090 +networks: + clarusnet: + driver: overlay \ No newline at end of file diff --git a/infrastructure/create-ecr-docker-registry-for-dev.sh b/infrastructure/create-ecr-docker-registry-for-dev.sh new file mode 100644 index 0000000000..e9a729f251 --- /dev/null +++ b/infrastructure/create-ecr-docker-registry-for-dev.sh @@ -0,0 +1,8 @@ +PATH="$PATH:/usr/local/bin" +APP_REPO_NAME="clarusway-repo/petclinic-app-dev" +AWS_REGION="us-east-1" +aws ecr create-repository \ + --repository-name ${APP_REPO_NAME} \ + --image-scanning-configuration scanOnPush=false \ + --image-tag-mutability MUTABLE \ + --region ${AWS_REGION} \ No newline at end of file diff --git a/infrastructure/create-qa-automation-environment.sh b/infrastructure/create-qa-automation-environment.sh new file mode 100644 index 0000000000..8a2fa03d82 --- /dev/null +++ b/infrastructure/create-qa-automation-environment.sh @@ -0,0 +1,31 @@ +# Environment variables +PATH="$PATH:/usr/local/bin" +APP_NAME="Petclinic" +CFN_KEYPAIR="Call-$APP_NAME-dev-${BUILD_NUMBER}.key" +CFN_TEMPLATE="./infrastructure/dev-docker-swarm-infrastructure-cfn-template.yml" +AWS_REGION="us-east-1" +export ANSIBLE_PRIVATE_KEY_FILE="${WORKSPACE}/${CFN_KEYPAIR}" +export ANSIBLE_HOST_KEY_CHECKING=False +export APP_STACK_NAME="Call-$APP_NAME-App-${BUILD_NUMBER}" +# Create key pair for Ansible +aws ec2 create-key-pair --region ${AWS_REGION} --key-name ${CFN_KEYPAIR} --query "KeyMaterial" --output text > ${CFN_KEYPAIR} +chmod 400 ${CFN_KEYPAIR} +# Create infrastructure for Docker Swarm +aws cloudformation create-stack --region ${AWS_REGION} --stack-name ${APP_STACK_NAME} --capabilities CAPABILITY_IAM --template-body file://${CFN_TEMPLATE} --parameters ParameterKey=KeyPairName,ParameterValue=${CFN_KEYPAIR} +# Install Docker Swarm environment on the infrastructure +# Update dynamic inventory (hosts/docker nodes) +sed -i "s/APP_STACK_NAME/$APP_STACK_NAME/" ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml +# Install common tools on all instances/nodes +ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml +# Initialize Docker Swarm on Grand Master +ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_initialize_docker_swarm.yaml +# Join the manager instances to the Swarm +ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_managers.yaml +# Join the worker instances to the Swarm +ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_workers.yaml +# Build, Deploy, Test the application +# Tear down the Docker Swarm infrastructure +aws cloudformation delete-stack --region ${AWS_REGION} --stack-name ${AWS_STACK_NAME} +# Delete key pair +aws ec2 delete-key-pair --region ${AWS_REGION} --key-name ${CFN_KEYPAIR} +rm -rf ${CFN_KEYPAIR} \ No newline at end of file diff --git a/infrastructure/dev-docker-swarm-infrastructure-cfn-template.yml b/infrastructure/dev-docker-swarm-infrastructure-cfn-template.yml new file mode 100644 index 0000000000..0302e30472 --- /dev/null +++ b/infrastructure/dev-docker-swarm-infrastructure-cfn-template.yml @@ -0,0 +1,179 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: > + This Cloudformation Template creates an infrastructure for Docker Swarm + with five EC2 Instances with Amazon Linux 2. Instances are configured + with custom security group allowing SSH (22), HTTP (80) UDP (4789, 7946), + and TCP(2377, 7946, 8080) connections from anywhere. + User needs to select appropriate key name when launching the template. +Parameters: + KeyPairName: + Description: Enter the name of your Key Pair for SSH connections. + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must one of the existing EC2 KeyPair +Resources: + RoleEnablingEC2forECR: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + EC2Profile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: #required + - !Ref RoleEnablingEC2forECR + DockerMachinesSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Enable SSH and HTTP for Docker Machines + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 2377 + ToPort: 2377 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 4789 + ToPort: 4789 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8080 + ToPort: 8080 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8088 + ToPort: 8088 + CidrIp: 0.0.0.0/0 + DockerMachineLT: + Type: "AWS::EC2::LaunchTemplate" + Properties: + LaunchTemplateData: + ImageId: ami-0947d2ba12ee1ff75 + InstanceType: t2.medium + KeyName: !Ref KeyPairName + IamInstanceProfile: + Arn: !GetAtt EC2Profile.Arn + SecurityGroupIds: + - !GetAtt DockerMachinesSecurityGroup.GroupId + TagSpecifications: + - ResourceType: instance + Tags: + - Key: app-stack-name + Value: !Sub ${AWS::StackName} + - Key: environment + Value: dev + DockerInstance1: + Type: AWS::EC2::Instance + DependsOn: + - "DockerInstance2" + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-1 + - Key: swarm-role + Value: grand-master + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 1st + DockerInstance2: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-2 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 2nd + DockerInstance3: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-3 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 3rd + DockerInstance4: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-4 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 4th + DockerInstance5: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-5 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 5th +Outputs: + 1stDockerInstanceDNSName: + Description: 1st Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance1.PublicDnsName + 2ndDockerInstanceDNSName: + Description: 2nd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance2.PublicDnsName + 3rdDockerInstanceDNSName: + Description: 3rd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance3.PublicDnsName + 4thDockerInstanceDNSName: + Description: 4th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance4.PublicDnsName + 5thDockerInstanceDNSName: + Description: 5th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance5.PublicDnsName \ No newline at end of file diff --git a/infrastructure/dev-server-for-petclinic-app-cfn-template.yml b/infrastructure/dev-server-for-petclinic-app-cfn-template.yml new file mode 100644 index 0000000000..9e3e93e251 --- /dev/null +++ b/infrastructure/dev-server-for-petclinic-app-cfn-template.yml @@ -0,0 +1,118 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: > + This Cloudformation template prepares development environment for + Petclinic Microservices Application. + User needs to select appropriate key name when launching the template. +Parameters: + KeyPairName: + Description: Enter the name of your Key Pair for SSH connections. + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must one of the existing EC2 KeyPair +Resources: + PetclinicDemoSG: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Enable SSH and HTTP for Petclinic Microservices + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 9090 + ToPort: 9090 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8080 + ToPort: 8080 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8081 + ToPort: 8081 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8082 + ToPort: 8082 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8083 + ToPort: 8083 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8888 + ToPort: 8888 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 9411 + ToPort: 9411 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 7979 + ToPort: 7979 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 3000 + ToPort: 3000 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 9091 + ToPort: 9091 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8761 + ToPort: 8761 + CidrIp: 0.0.0.0/0 + PetclinicServerLT: + Type: "AWS::EC2::LaunchTemplate" + Properties: + LaunchTemplateData: + ImageId: ami-0947d2ba12ee1ff75 + InstanceType: t2.medium + KeyName: !Ref KeyPairName + SecurityGroupIds: + - !GetAtt PetclinicDemoSG.GroupId + UserData: + Fn::Base64: | + + #! /bin/bash + # update os + yum update -y + # set hostname as petclinic-dev-server + hostnamectl set-hostname petclinic-dev-server + # install docker + amazon-linux-extras install docker -y + systemctl start docker + systemctl enable docker + usermod -a -G docker ec2-user + # install docker compose + curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + # install JDK 11 + yum install java-11-amazon-corretto -y + # install Git + yum install git -y + cd /home/ec2-user + git clone https://github.com/huseyin-yigit/microservices-ci-cd-pipeline-with-petclinic-app.git + git fetch + git checkout dev + + + + + PetclinicServer: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref PetclinicServerLT + Version: !GetAtt PetclinicServerLT.LatestVersionNumber + Tags: + - Key: Name + Value: !Sub Petclinic App Dev Server of ${AWS::StackName} +Outputs: + PetclinicServerDNSName: + Description: Petclinic App URL + Value: !GetAtt PetclinicServer.PublicDnsName \ No newline at end of file diff --git a/infrastructure/docker-swarm-infrastructure-cfn-template.yml b/infrastructure/docker-swarm-infrastructure-cfn-template.yml new file mode 100644 index 0000000000..091aa3ccc9 --- /dev/null +++ b/infrastructure/docker-swarm-infrastructure-cfn-template.yml @@ -0,0 +1,173 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: | + This Cloudformation Template creates an infrastructure for Docker Swarm + with five EC2 Instances with Amazon Linux 2. Instances are configured + with custom security group allowing SSH (22), HTTP (80) UDP (4789, 7946), + and TCP(2377, 7946, 8080) connections from anywhere. + User needs to select appropriate key name when launching the template. +Parameters: + KeyPairName: + Description: Enter the name of your Key Pair for SSH connections. + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must one of the existing EC2 KeyPair +Resources: + RoleEnablingEC2forECR: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + EC2Profile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: #required + - !Ref RoleEnablingEC2forECR + DockerMachinesSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Enable SSH and HTTP for Docker Machines + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 2377 + ToPort: 2377 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 4789 + ToPort: 4789 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8080 + ToPort: 8080 + CidrIp: 0.0.0.0/0 + DockerMachineLT: + Type: "AWS::EC2::LaunchTemplate" + Properties: + LaunchTemplateData: + ImageId: ami-0947d2ba12ee1ff75 + InstanceType: t2.micro + KeyName: !Ref KeyPairName + IamInstanceProfile: + Arn: !GetAtt EC2Profile.Arn + SecurityGroupIds: + - !GetAtt DockerMachinesSecurityGroup.GroupId + TagSpecifications: + - ResourceType: instance + Tags: + - Key: app-stack-name + Value: !Sub ${AWS::StackName} + - Key: environment + Value: dev + DockerInstance1: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-1 + - Key: swarm-role + Value: grand-master + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 1st + DockerInstance2: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-2 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 2nd + DockerInstance3: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-3 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 3rd + DockerInstance4: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-4 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 4th + DockerInstance5: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-5 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 5th +Outputs: + 1stDockerInstanceDNSName: + Description: 1st Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance1.PublicDnsName + 2ndDockerInstanceDNSName: + Description: 2nd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance2.PublicDnsName + 3rdDockerInstanceDNSName: + Description: 3rd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance3.PublicDnsName + 4thDockerInstanceDNSName: + Description: 4th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance4.PublicDnsName + 5thDockerInstanceDNSName: + Description: 5th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance5.PublicDnsName \ No newline at end of file diff --git a/infrastructure/jenkins-server-cfn-template.yml b/infrastructure/jenkins-server-cfn-template.yml new file mode 100644 index 0000000000..4beea17421 --- /dev/null +++ b/infrastructure/jenkins-server-cfn-template.yml @@ -0,0 +1,153 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: > + This Cloudformation Template creates a Jenkins Server using JDK 11 on EC2 Instance. + Jenkins Server is enabled with Git, Docker and Docker Compose, + AWS CLI Version 2, ECR Credential Helper, Python 3, Ansible, and Boto3. + Jenkins Server will run on Amazon Linux 2 EC2 Instance with + custom security group allowing HTTP(80, 8080) and SSH (22) connections from anywhere. +Parameters: + KeyPairName: + Description: Enter the name of your Key Pair for SSH connections. + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must one of the existing EC2 KeyPair +Resources: + EmpoweringPolicyforJenkinsServer: + Type: "AWS::IAM::ManagedPolicy" + Properties: + PolicyDocument: #required + Version: 2012-10-17 + Statement: + - Effect: Allow + Action: + - iam:AddRoleToInstanceProfile + - iam:CreateInstanceProfile + - iam:CreatePolicy + - iam:CreateRole + - iam:DeleteInstanceProfile + - iam:DeletePolicy + - iam:DeleteRole + - iam:GetPolicy + - iam:GetRole + - iam:ListPolicyVersions + - iam:AttachRolePolicy + - iam:DetachRolePolicy + - iam:PassRole + - iam:RemoveRoleFromInstanceProfile + - iam:GetInstanceProfile + Resource: "*" + - Effect: Allow + Action: + - ec2:* + Resource: "*" + EmpoweringRoleforJenkinsServer: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + - arn:aws:iam::aws:policy/AWSCloudFormationFullAccess + - !Ref EmpoweringPolicyforJenkinsServer + JenkinsServerEC2Profile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: #required + - !Ref EmpoweringRoleforJenkinsServer + JenkinsServerSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Enable SSH and HTTP for Jenkins Server + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8080 + ToPort: 8080 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + JenkinsServer: + Type: AWS::EC2::Instance + Properties: + ImageId: ami-0947d2ba12ee1ff75 + InstanceType: t2.medium + KeyName: !Ref KeyPairName + IamInstanceProfile: !Ref JenkinsServerEC2Profile + SecurityGroupIds: + - !GetAtt JenkinsServerSecurityGroup.GroupId + Tags: + - Key: Name + Value: !Sub Jenkins Server of ${AWS::StackName} + - Key: server + Value: jenkins + UserData: + Fn::Base64: | + #! /bin/bash + # update os + yum update -y + # set server hostname as jenkins-server + hostnamectl set-hostname jenkins-server + # install git + yum install git -y + # install java 11 + yum install java-11-amazon-corretto -y + # install jenkins + wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat/jenkins.repo + rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key + yum install jenkins -y + systemctl start jenkins + systemctl enable jenkins + # install docker + amazon-linux-extras install docker -y + systemctl start docker + systemctl enable docker + usermod -a -G docker ec2-user + usermod -a -G docker jenkins + # configure docker as cloud agent for jenkins + cp /lib/systemd/system/docker.service /lib/systemd/system/docker.service.bak + sed -i 's/^ExecStart=.*/ExecStart=\/usr\/bin\/dockerd -H tcp:\/\/127.0.0.1:2375 -H unix:\/\/\/var\/run\/docker.sock/g' /lib/systemd/system/docker.service + systemctl daemon-reload + systemctl restart docker + systemctl restart jenkins + # install docker compose + curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" \ + -o /usr/local/bin/docker-compose + chmod +x /usr/local/bin/docker-compose + # uninstall aws cli version 1 + rm -rf /bin/aws + # install aws cli version 2 + curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" + unzip awscliv2.zip + ./aws/install + # install aws ecr credential helper + yum install amazon-ecr-credential-helper -y + mkdir -p /home/jenkins/.docker + cd /home/jenkins/.docker + echo '{"credsStore": "ecr-login"}' > config.json + # install python 3 + yum install python3 -y + # install ansible + pip3 install ansible + # install boto3 + pip3 install boto3 +Outputs: + JenkinsDNS: + Description: Jenkins Server DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt JenkinsServer.PublicDnsName + JenkinsURL: + Description: Jenkins Server URL + Value: !Sub + - http://${PublicAddress}:8080 + - PublicAddress: !GetAtt JenkinsServer.PublicDnsName \ No newline at end of file diff --git a/infrastructure/qa-docker-swarm-infrastructure-cfn-template.yml b/infrastructure/qa-docker-swarm-infrastructure-cfn-template.yml new file mode 100644 index 0000000000..602e2e1ceb --- /dev/null +++ b/infrastructure/qa-docker-swarm-infrastructure-cfn-template.yml @@ -0,0 +1,179 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: > + This Cloudformation Template creates an infrastructure for Docker Swarm + with five EC2 Instances with Amazon Linux 2. Instances are configured + with custom security group allowing SSH (22), HTTP (80) UDP (4789, 7946), + and TCP(2377, 7946, 8080) connections from anywhere. + User needs to select appropriate key name when launching the template. +Parameters: + KeyPairName: + Description: Enter the name of your Key Pair for SSH connections. + Type: AWS::EC2::KeyPair::KeyName + ConstraintDescription: Must one of the existing EC2 KeyPair +Resources: + RoleEnablingEC2forECR: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Statement: + - Effect: Allow + Principal: + Service: + - ec2.amazonaws.com + Action: + - 'sts:AssumeRole' + ManagedPolicyArns: + - arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess + EC2Profile: + Type: "AWS::IAM::InstanceProfile" + Properties: + Roles: #required + - !Ref RoleEnablingEC2forECR + DockerMachinesSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: Enable SSH and HTTP for Docker Machines + SecurityGroupIngress: + - IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 22 + ToPort: 22 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 2377 + ToPort: 2377 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 7946 + ToPort: 7946 + CidrIp: 0.0.0.0/0 + - IpProtocol: udp + FromPort: 4789 + ToPort: 4789 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8080 + ToPort: 8080 + CidrIp: 0.0.0.0/0 + - IpProtocol: tcp + FromPort: 8088 + ToPort: 8088 + CidrIp: 0.0.0.0/0 + DockerMachineLT: + Type: "AWS::EC2::LaunchTemplate" + Properties: + LaunchTemplateData: + ImageId: ami-0947d2ba12ee1ff75 + InstanceType: t2.medium + KeyName: !Ref KeyPairName + IamInstanceProfile: + Arn: !GetAtt EC2Profile.Arn + SecurityGroupIds: + - !GetAtt DockerMachinesSecurityGroup.GroupId + TagSpecifications: + - ResourceType: instance + Tags: + - Key: app-stack-name + Value: !Sub ${AWS::StackName} + - Key: environment + Value: qa + DockerInstance1: + Type: AWS::EC2::Instance + DependsOn: + - "DockerInstance2" + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-1 + - Key: swarm-role + Value: grand-master + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 1st + DockerInstance2: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-2 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 2nd + DockerInstance3: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-3 + - Key: swarm-role + Value: manager + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 3rd + DockerInstance4: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-4 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 4th + DockerInstance5: + Type: AWS::EC2::Instance + Properties: + LaunchTemplate: + LaunchTemplateId: !Ref DockerMachineLT + Version: !GetAtt DockerMachineLT.LatestVersionNumber + Tags: + - Key: server + Value: docker-instance-5 + - Key: swarm-role + Value: worker + - Key: Name + Value: !Sub ${AWS::StackName} Docker Machine 5th +Outputs: + 1stDockerInstanceDNSName: + Description: 1st Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance1.PublicDnsName + 2ndDockerInstanceDNSName: + Description: 2nd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance2.PublicDnsName + 3rdDockerInstanceDNSName: + Description: 3rd Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance3.PublicDnsName + 4thDockerInstanceDNSName: + Description: 4th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance4.PublicDnsName + 5thDockerInstanceDNSName: + Description: 5th Docker Instance DNS Name + Value: !Sub + - ${PublicAddress} + - PublicAddress: !GetAtt DockerInstance5.PublicDnsName \ No newline at end of file diff --git a/jenkins/build-and-deploy-petclinic-on-qa-env-manually.sh b/jenkins/build-and-deploy-petclinic-on-qa-env-manually.sh new file mode 100644 index 0000000000..db30b11526 --- /dev/null +++ b/jenkins/build-and-deploy-petclinic-on-qa-env-manually.sh @@ -0,0 +1,22 @@ +PATH="$PATH:/usr/local/bin" +APP_NAME="petclinic" +APP_REPO_NAME="huseyin-repo/petclinic-app-qa" +APP_STACK_NAME="Huseyin-petclinic-App-QA-1" +CFN_KEYPAIR="huseyin-petclinic-qa.key" +AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) +AWS_REGION="us-east-1" +ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com" +export ANSIBLE_PRIVATE_KEY_FILE="${JENKINS_HOME}/.ssh/${CFN_KEYPAIR}" +export ANSIBLE_HOST_KEY_CHECKING="False" +echo 'Packaging the App into Jars with Maven' +. ./jenkins/package-with-maven-container.sh +echo 'Preparing QA Tags for Docker Images' +. ./jenkins/prepare-tags-ecr-for-qa-docker-images.sh +echo 'Building App QA Images' +. ./jenkins/build-qa-docker-images-for-ecr.sh +echo "Pushing App QA Images to ECR Repo" +. ./jenkins/push-qa-docker-images-to-ecr.sh +echo 'Deploying App on Swarm' +. ./ansible/scripts/deploy_app_on_qa_environment.sh +echo 'Deleting all local images' +docker image prune -af \ No newline at end of file diff --git a/jenkins/build-dev-docker-images-for-ecr.sh b/jenkins/build-dev-docker-images-for-ecr.sh new file mode 100644 index 0000000000..4ea98df327 --- /dev/null +++ b/jenkins/build-dev-docker-images-for-ecr.sh @@ -0,0 +1,10 @@ +docker build --force-rm -t "${IMAGE_TAG_ADMIN_SERVER}" "${WORKSPACE}/spring-petclinic-admin-server" +docker build --force-rm -t "${IMAGE_TAG_API_GATEWAY}" "${WORKSPACE}/spring-petclinic-api-gateway" +docker build --force-rm -t "${IMAGE_TAG_CONFIG_SERVER}" "${WORKSPACE}/spring-petclinic-config-server" +docker build --force-rm -t "${IMAGE_TAG_CUSTOMERS_SERVICE}" "${WORKSPACE}/spring-petclinic-customers-service" +docker build --force-rm -t "${IMAGE_TAG_DISCOVERY_SERVER}" "${WORKSPACE}/spring-petclinic-discovery-server" +docker build --force-rm -t "${IMAGE_TAG_HYSTRIX_DASHBOARD}" "${WORKSPACE}/spring-petclinic-hystrix-dashboard" +docker build --force-rm -t "${IMAGE_TAG_VETS_SERVICE}" "${WORKSPACE}/spring-petclinic-vets-service" +docker build --force-rm -t "${IMAGE_TAG_VISITS_SERVICE}" "${WORKSPACE}/spring-petclinic-visits-service" +docker build --force-rm -t "${IMAGE_TAG_GRAFANA_SERVICE}" "${WORKSPACE}/docker/grafana" +docker build --force-rm -t "${IMAGE_TAG_PROMETHEUS_SERVICE}" "${WORKSPACE}/docker/prometheus" \ No newline at end of file diff --git a/jenkins/build-qa-docker-images-for-ecr.sh b/jenkins/build-qa-docker-images-for-ecr.sh new file mode 100644 index 0000000000..7ae5bfdfde --- /dev/null +++ b/jenkins/build-qa-docker-images-for-ecr.sh @@ -0,0 +1,11 @@ +aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY} +docker push "${IMAGE_TAG_ADMIN_SERVER}" +docker push "${IMAGE_TAG_API_GATEWAY}" +docker push "${IMAGE_TAG_CONFIG_SERVER}" +docker push "${IMAGE_TAG_CUSTOMERS_SERVICE}" +docker push "${IMAGE_TAG_DISCOVERY_SERVER}" +docker push "${IMAGE_TAG_HYSTRIX_DASHBOARD}" +docker push "${IMAGE_TAG_VETS_SERVICE}" +docker push "${IMAGE_TAG_VISITS_SERVICE}" +docker push "${IMAGE_TAG_GRAFANA_SERVICE}" +docker push "${IMAGE_TAG_PROMETHEUS_SERVICE}" \ No newline at end of file diff --git a/jenkins/create-permanent-key-pair-for-qa-environment.sh b/jenkins/create-permanent-key-pair-for-qa-environment.sh new file mode 100644 index 0000000000..3b6013abf1 --- /dev/null +++ b/jenkins/create-permanent-key-pair-for-qa-environment.sh @@ -0,0 +1,8 @@ +PATH="$PATH:/usr/local/bin" +APP_NAME="petclinic" +CFN_KEYPAIR="huseyin-${APP_NAME}-qa.key" +AWS_REGION="us-east-1" +aws ec2 create-key-pair --region ${AWS_REGION} --key-name ${CFN_KEYPAIR} --query "KeyMaterial" --output text > ${CFN_KEYPAIR} +chmod 400 ${CFN_KEYPAIR} +cp ${CFN_KEYPAIR} ${JENKINS_HOME}/.ssh/${CFN_KEYPAIR} +ls -al ${JENKINS_HOME}/.ssh \ No newline at end of file diff --git a/jenkins/jenkins-petclinic-ci-job.sh b/jenkins/jenkins-petclinic-ci-job.sh new file mode 100644 index 0000000000..66e6e22f18 --- /dev/null +++ b/jenkins/jenkins-petclinic-ci-job.sh @@ -0,0 +1,2 @@ +echo 'Running Unit Tests on Petclinic Application' +docker run --rm -v $HOME/.m2:/root/.m2 -v `pwd`:/app -w /app maven:3.6.3-openjdk-11 mvn clean test \ No newline at end of file diff --git a/jenkins/jenkinsfile-create-qa-environment-on-docker-swarm b/jenkins/jenkinsfile-create-qa-environment-on-docker-swarm new file mode 100644 index 0000000000..f198e46c38 --- /dev/null +++ b/jenkins/jenkinsfile-create-qa-environment-on-docker-swarm @@ -0,0 +1,65 @@ +pipeline { + agent { label "master" } + environment { + PATH=sh(script:"echo $PATH:/usr/local/bin", returnStdout:true).trim() + APP_NAME="petclinic" + APP_STACK_NAME="Huseyin-$APP_NAME-App-QA-${BUILD_NUMBER}" + AWS_REGION="us-east-1" + CFN_KEYPAIR="huseyin-${APP_NAME}-qa.key" + CFN_TEMPLATE="./infrastructure/qa-docker-swarm-infrastructure-cfn-template.yml" + ANSIBLE_PRIVATE_KEY_FILE="${JENKINS_HOME}/.ssh/${CFN_KEYPAIR}" + ANSIBLE_HOST_KEY_CHECKING="False" + } + stages { + stage('Create QA Environment Infrastructure') { + steps { + echo 'Creating Infrastructure for QA Environment with Cloudfomation' + sh "aws cloudformation create-stack --region ${AWS_REGION} --stack-name ${APP_STACK_NAME} --capabilities CAPABILITY_IAM --template-body file://${CFN_TEMPLATE} --parameters ParameterKey=KeyPairName,ParameterValue=${CFN_KEYPAIR}" + script { + while(true) { + echo "Docker Grand Master is not UP and running yet. Will try to reach again after 10 seconds..." + sleep(10) + ip = sh(script:"aws ec2 describe-instances --region ${AWS_REGION} --filters Name=tag-value,Values=grand-master Name=tag-value,Values=${APP_STACK_NAME} --query Reservations[*].Instances[*].[PublicIpAddress] --output text", returnStdout:true).trim() + if (ip.length() >= 7) { + echo "Docker Grand Master Public Ip Address Found: $ip" + env.GRAND_MASTER_PUBLIC_IP = "$ip" + break + } + } + while(true) { + try{ + sh "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${JENKINS_HOME}/.ssh/${CFN_KEYPAIR} ec2-user@${GRAND_MASTER_PUBLIC_IP} hostname" + echo "Docker Grand Master is reachable with SSH." + break + } + catch(Exception){ + echo "Could not connect to Docker Grand Master with SSH, I will try again in 10 seconds" + sleep(10) + } + } + } + } + } + stage('Create Docker Swarm for QA Environment') { + steps { + echo "Setup Docker Swarm for QA Environment for ${APP_NAME} App" + echo "Update dynamic environment" + sh "sed -i 's/APP_STACK_NAME/${APP_STACK_NAME}/' ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml" + echo "Swarm Setup for all nodes (instances)" + sh "ansible-playbook -i ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml" + echo "Swarm Setup for Grand Master node" + sh "ansible-playbook -i ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_initialize_docker_swarm.yaml" + echo "Swarm Setup for Other Managers nodes" + sh "ansible-playbook -i ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_managers.yaml" + echo "Swarm Setup for Workers nodes" + sh "ansible-playbook -i ./ansible/inventory/qa_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_workers.yaml" + } + } + } + post { + failure { + echo 'Tear down the Docker Swarm infrastructure using AWS CLI' + sh "aws cloudformation delete-stack --region ${AWS_REGION} --stack-name ${APP_STACK_NAME}" + } + } +} \ No newline at end of file diff --git a/jenkins/jenkinsfile-petclinic-nightly b/jenkins/jenkinsfile-petclinic-nightly new file mode 100644 index 0000000000..f99776a6e0 --- /dev/null +++ b/jenkins/jenkinsfile-petclinic-nightly @@ -0,0 +1,179 @@ +pipeline { + agent { label "master" } + environment { + PATH=sh(script:"echo $PATH:/usr/local/bin", returnStdout:true).trim() + APP_NAME="petclinic" + APP_STACK_NAME="Huseyin-${APP_NAME}-app-dev-${BUILD_NUMBER}" + APP_REPO_NAME="huseyin-repo/${APP_NAME}-app-dev" + AWS_ACCOUNT_ID=sh(script:'export PATH="$PATH:/usr/local/bin" && aws sts get-caller-identity --query Account --output text', returnStdout:true).trim() + AWS_REGION="us-east-1" + ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com" + CFN_KEYPAIR="huseyin-${APP_NAME}-dev-${BUILD_NUMBER}.key" + CFN_TEMPLATE="./infrastructure/dev-docker-swarm-infrastructure-cfn-template.yml" + ANSIBLE_PRIVATE_KEY_FILE="${WORKSPACE}/${CFN_KEYPAIR}" + ANSIBLE_HOST_KEY_CHECKING="False" + } + stages { + stage('Create ECR Repo'){ + steps { + echo "Creating ECR Repo for ${APP_NAME} app" + sh """ + aws ecr create-repository \ + --repository-name ${APP_REPO_NAME} \ + --image-scanning-configuration scanOnPush=false \ + --image-tag-mutability MUTABLE \ + --region ${AWS_REGION} + """ + } + } + stage('Package Application'){ + steps { + echo 'Packaging the app into jars with maven' + sh ". ./jenkins/package-with-maven-container.sh" + } + } + stage('Prepare Tags for Docker Images'){ + steps { + echo 'Preparing Tags for Docker Images' + script { + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-admin-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_ADMIN_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:admin-server-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-api-gateway/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_API_GATEWAY="${ECR_REGISTRY}/${APP_REPO_NAME}:api-gateway-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-config-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_CONFIG_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:config-server-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-customers-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_CUSTOMERS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:customers-service-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-discovery-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_DISCOVERY_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:discovery-server-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-hystrix-dashboard/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_HYSTRIX_DASHBOARD="${ECR_REGISTRY}/${APP_REPO_NAME}:hystrix-dashboard-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-vets-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_VETS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:vets-service-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-visits-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_VISITS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:visits-service-v${MVN_VERSION}-b${BUILD_NUMBER}" + env.IMAGE_TAG_GRAFANA_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:grafana-service" + env.IMAGE_TAG_PROMETHEUS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:prometheus-service" + } + } + } + stage('Build App Docker Images'){ + steps { + echo 'Building App Dev Images' + sh ". ./jenkins/build-dev-docker-images-for-ecr.sh" + sh 'docker image ls' + } + } + stage('Push Images to ECR Repo'){ + steps { + echo "Pushing ${APP_NAME} App Images to ECR Repo" + sh ". ./jenkins/push-dev-docker-images-to-ecr.sh" + } + } + stage('Create Key Pair for Ansible'){ + steps { + echo "Creating Key Pair for ${APP_NAME} App" + sh "aws ec2 create-key-pair --region ${AWS_REGION} --key-name ${CFN_KEYPAIR} --query KeyMaterial --output text > ${CFN_KEYPAIR}" + sh "chmod 400 ${CFN_KEYPAIR}" + } + } + stage('Create QA Automation Infrastructure') { + steps { + echo 'Creating QA Automation Infrastructure for Dev Environment with Cloudfomation' + sh "aws cloudformation create-stack --region ${AWS_REGION} --stack-name ${APP_STACK_NAME} --capabilities CAPABILITY_IAM --template-body file://${CFN_TEMPLATE} --parameters ParameterKey=KeyPairName,ParameterValue=${CFN_KEYPAIR}" + + script { + while(true) { + echo "Docker Grand Master is not UP and running yet. Will try to reach again after 10 seconds..." + sleep(10) + + ip = sh(script:"aws ec2 describe-instances --region ${AWS_REGION} --filters Name=tag-value,Values=grand-master Name=tag-value,Values=${APP_STACK_NAME} --query Reservations[*].Instances[*].[PublicIpAddress] --output text", returnStdout:true).trim() + + if (ip.length() >= 7) { + echo "Docker Grand Master Public Ip Address Found: $ip" + env.GRAND_MASTER_PUBLIC_IP = "$ip" + break + } + } + while(true) { + try{ + sh "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i ${WORKSPACE}/${CFN_KEYPAIR} ec2-user@${GRAND_MASTER_PUBLIC_IP} hostname" + echo "Docker Grand Master is reachable with SSH." + break + } + catch(Exception){ + echo "Could not connect to Docker Grand Master with SSH, I will try again in 10 seconds" + sleep(10) + } + } + } + } + } + stage('Create Docker Swarm for QA Automation Build'){ + steps { + echo "Setup Docker Swarm for QA Automation Build for ${APP_NAME} App" + echo "Update dynamic environment" + sh "sed -i 's/APP_STACK_NAME/${APP_STACK_NAME}/' ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml" + echo "Swarm Setup for all nodes (instances)" + sh "ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_setup_for_all_docker_swarm_instances.yaml" + echo "Swarm Setup for Grand Master node" + sh "ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_initialize_docker_swarm.yaml" + echo "Swarm Setup for Other Managers nodes" + sh "ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_managers.yaml" + echo "Swarm Setup for Workers nodes" + sh "ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b ./ansible/playbooks/pb_join_docker_swarm_workers.yaml" + } + } + stage('Deploy App on Docker Swarm'){ + steps { + echo 'Deploying App on Swarm' + sh 'envsubst < docker-compose-swarm-dev.yml > docker-compose-swarm-dev-tagged.yml' + sh 'ansible-playbook -i ./ansible/inventory/dev_stack_dynamic_inventory_aws_ec2.yaml -b --extra-vars "workspace=${WORKSPACE} app_name=${APP_NAME} aws_region=${AWS_REGION} ecr_registry=${ECR_REGISTRY}" ./ansible/playbooks/pb_deploy_app_on_docker_swarm.yaml' + } + } + stage('Test the Application Deployment'){ + steps { + echo "Check if the ${APP_NAME} app is ready or not" + script { + while(true) { + try{ + sh "curl -s ${GRAND_MASTER_PUBLIC_IP}:8080" + echo "${APP_NAME} app is successfully deployed." + break + } + catch(Exception){ + echo "Could not connect to ${APP_NAME} app" + sleep(5) + } + } + } + } + + } + stage('Run QA Automation Tests'){ + steps { + echo "Run the Selenium Functional Test on QA Environment" + sh 'ansible-playbook -vvv --connection=local --inventory 127.0.0.1, --extra-vars "workspace=${WORKSPACE} master_public_ip=${GRAND_MASTER_PUBLIC_IP}" ./ansible/playbooks/pb_run_selenium_jobs.yaml' + } + } + } + post { + always { + echo 'Deleting all local images' + sh 'docker image prune -af' + echo 'Delete the Image Repository on ECR' + sh """ + aws ecr delete-repository \ + --repository-name ${APP_REPO_NAME} \ + --region ${AWS_REGION}\ + --force + """ + echo 'Tear down the Docker Swarm infrastructure using AWS CLI' + sh "aws cloudformation delete-stack --region ${AWS_REGION} --stack-name ${APP_STACK_NAME}" + echo "Delete existing key pair using AWS CLI" + sh "aws ec2 delete-key-pair --region ${AWS_REGION} --key-name ${CFN_KEYPAIR}" + sh "rm -rf ${CFN_KEYPAIR}" + } + + } +} \ No newline at end of file diff --git a/jenkins/jenkinsfile-petclinic-weekly-qa b/jenkins/jenkinsfile-petclinic-weekly-qa new file mode 100644 index 0000000000..6a57e49144 --- /dev/null +++ b/jenkins/jenkinsfile-petclinic-weekly-qa @@ -0,0 +1,73 @@ +pipeline { + agent { label "master" } + environment { + PATH=sh(script:"echo $PATH:/usr/local/bin", returnStdout:true).trim() + APP_NAME="petclinic" + APP_REPO_NAME="huseyin-repo/petclinic-app-qa" + APP_STACK_NAME="Huseyin-petclinic-App-QA-1" + CFN_KEYPAIR="huseyin-petclinic-qa.key" + AWS_ACCOUNT_ID=sh(script:'export PATH="$PATH:/usr/local/bin" && aws sts get-caller-identity --query Account --output text', returnStdout:true).trim() + AWS_REGION="us-east-1" + ECR_REGISTRY="${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com" + ANSIBLE_PRIVATE_KEY_FILE="${JENKINS_HOME}/.ssh/${CFN_KEYPAIR}" + ANSIBLE_HOST_KEY_CHECKING="False" + } + stages { + stage('Package Application') { + steps { + echo 'Packaging the app into jars with maven' + sh ". ./jenkins/package-with-maven-container.sh" + } + } + stage('Prepare Tags for Docker Images') { + steps { + echo 'Preparing Tags for Docker Images' + script { + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-admin-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_ADMIN_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:admin-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-api-gateway/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_API_GATEWAY="${ECR_REGISTRY}/${APP_REPO_NAME}:api-gateway-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-config-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_CONFIG_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:config-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-customers-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_CUSTOMERS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:customers-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-discovery-server/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_DISCOVERY_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:discovery-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-hystrix-dashboard/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_HYSTRIX_DASHBOARD="${ECR_REGISTRY}/${APP_REPO_NAME}:hystrix-dashboard-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-vets-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_VETS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:vets-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + MVN_VERSION=sh(script:'. ${WORKSPACE}/spring-petclinic-visits-service/target/maven-archiver/pom.properties && echo $version', returnStdout:true).trim() + env.IMAGE_TAG_VISITS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:visits-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" + env.IMAGE_TAG_GRAFANA_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:grafana-service" + env.IMAGE_TAG_PROMETHEUS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:prometheus-service" + } + } + } + stage('Build App Docker Images') { + steps { + echo 'Building App Dev Images' + sh ". ./jenkins/build-qa-docker-images-for-ecr.sh" + sh 'docker image ls' + } + } + stage('Push Images to ECR Repo') { + steps { + echo "Pushing ${APP_NAME} App Images to ECR Repo" + sh ". ./jenkins/push-qa-docker-images-to-ecr.sh" + } + } + stage('Deploy App on Docker Swarm'){ + steps { + echo 'Deploying App on Swarm' + sh '. ./ansible/scripts/deploy_app_on_qa_environment.sh' + } + } + } + post { + always { + echo 'Deleting all local images' + sh 'docker image prune -af' + } + } +} \ No newline at end of file diff --git a/jenkins/package-with-maven-container.sh b/jenkins/package-with-maven-container.sh new file mode 100644 index 0000000000..6d691a5ed4 --- /dev/null +++ b/jenkins/package-with-maven-container.sh @@ -0,0 +1 @@ +docker run --rm -v $HOME/.m2:/root/.m2 -v $WORKSPACE:/app -w /app maven:3.6-openjdk-11 mvn clean package \ No newline at end of file diff --git a/jenkins/prepare-tags-ecr-for-dev-docker-images.sh b/jenkins/prepare-tags-ecr-for-dev-docker-images.sh new file mode 100644 index 0000000000..8fff3dbf6d --- /dev/null +++ b/jenkins/prepare-tags-ecr-for-dev-docker-images.sh @@ -0,0 +1,18 @@ +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-admin-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_ADMIN_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:admin-server-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-api-gateway/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_API_GATEWAY="${ECR_REGISTRY}/${APP_REPO_NAME}:api-gateway-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-config-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_CONFIG_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:config-server-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-customers-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_CUSTOMERS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:customers-service-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-discovery-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_DISCOVERY_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:discovery-server-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-hystrix-dashboard/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_HYSTRIX_DASHBOARD="${ECR_REGISTRY}/${APP_REPO_NAME}:hystrix-dashboard-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-vets-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_VETS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:vets-service-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-visits-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_VISITS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:visits-service-v${MVN_VERSION}-b${BUILD_NUMBER}" +export IMAGE_TAG_GRAFANA_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:grafana-service" +export IMAGE_TAG_PROMETHEUS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:prometheus-service" \ No newline at end of file diff --git a/jenkins/prepare-tags-ecr-for-qa-docker-images.sh b/jenkins/prepare-tags-ecr-for-qa-docker-images.sh new file mode 100644 index 0000000000..d90e8db9c2 --- /dev/null +++ b/jenkins/prepare-tags-ecr-for-qa-docker-images.sh @@ -0,0 +1,18 @@ +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-admin-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_ADMIN_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:admin-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-api-gateway/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_API_GATEWAY="${ECR_REGISTRY}/${APP_REPO_NAME}:api-gateway-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-config-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_CONFIG_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:config-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-customers-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_CUSTOMERS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:customers-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-discovery-server/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_DISCOVERY_SERVER="${ECR_REGISTRY}/${APP_REPO_NAME}:discovery-server-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-hystrix-dashboard/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_HYSTRIX_DASHBOARD="${ECR_REGISTRY}/${APP_REPO_NAME}:hystrix-dashboard-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-vets-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_VETS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:vets-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +MVN_VERSION=$(. ${WORKSPACE}/spring-petclinic-visits-service/target/maven-archiver/pom.properties && echo $version) +export IMAGE_TAG_VISITS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:visits-service-qa-v${MVN_VERSION}-b${BUILD_NUMBER}" +export IMAGE_TAG_GRAFANA_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:grafana-service" +export IMAGE_TAG_PROMETHEUS_SERVICE="${ECR_REGISTRY}/${APP_REPO_NAME}:prometheus-service" \ No newline at end of file diff --git a/jenkins/push-dev-docker-images-to-ecr.sh b/jenkins/push-dev-docker-images-to-ecr.sh new file mode 100644 index 0000000000..7ae5bfdfde --- /dev/null +++ b/jenkins/push-dev-docker-images-to-ecr.sh @@ -0,0 +1,11 @@ +aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${ECR_REGISTRY} +docker push "${IMAGE_TAG_ADMIN_SERVER}" +docker push "${IMAGE_TAG_API_GATEWAY}" +docker push "${IMAGE_TAG_CONFIG_SERVER}" +docker push "${IMAGE_TAG_CUSTOMERS_SERVICE}" +docker push "${IMAGE_TAG_DISCOVERY_SERVER}" +docker push "${IMAGE_TAG_HYSTRIX_DASHBOARD}" +docker push "${IMAGE_TAG_VETS_SERVICE}" +docker push "${IMAGE_TAG_VISITS_SERVICE}" +docker push "${IMAGE_TAG_GRAFANA_SERVICE}" +docker push "${IMAGE_TAG_PROMETHEUS_SERVICE}" \ No newline at end of file diff --git a/k8s/base/admin-server-deployment.yaml b/k8s/base/admin-server-deployment.yaml new file mode 100644 index 0000000000..fa936fb8ff --- /dev/null +++ b/k8s/base/admin-server-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: admin-server + name: admin-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: admin-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: admin-server + spec: + containers: + - image: IMAGE_TAG_ADMIN_SERVER + name: admin-server + ports: + - containerPort: 9090 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/admin-server-service.yaml b/k8s/base/admin-server-service.yaml new file mode 100644 index 0000000000..d51aae79c9 --- /dev/null +++ b/k8s/base/admin-server-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: admin-server + name: admin-server +spec: + ports: + - name: "9090" + port: 9090 + targetPort: 9090 + selector: + io.kompose.service: admin-server +status: + loadBalancer: {} diff --git a/k8s/base/api-gateway-deployment.yaml b/k8s/base/api-gateway-deployment.yaml new file mode 100644 index 0000000000..3c39d39889 --- /dev/null +++ b/k8s/base/api-gateway-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: api-gateway + name: api-gateway +spec: + replicas: 2 + selector: + matchLabels: + io.kompose.service: api-gateway + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: api-gateway + spec: + containers: + - image: IMAGE_TAG_API_GATEWAY + name: api-gateway + ports: + - containerPort: 8080 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/api-gateway-ingress.yaml b/k8s/base/api-gateway-ingress.yaml new file mode 100644 index 0000000000..64612b9038 --- /dev/null +++ b/k8s/base/api-gateway-ingress.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: api-gateway + name: api-gateway +spec: + rules: + - host: petclinic.clarusway.us + http: + paths: + - backend: + serviceName: api-gateway + servicePort: 8080 +status: + loadBalancer: {} diff --git a/k8s/base/api-gateway-service.yaml b/k8s/base/api-gateway-service.yaml new file mode 100644 index 0000000000..9674c75d04 --- /dev/null +++ b/k8s/base/api-gateway-service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: api-gateway + name: api-gateway +spec: + ports: + - name: "8080" + port: 8080 + targetPort: 8080 + selector: + io.kompose.service: api-gateway +status: + loadBalancer: {} diff --git a/k8s/base/config-server-deployment.yaml b/k8s/base/config-server-deployment.yaml new file mode 100644 index 0000000000..aa5b54436a --- /dev/null +++ b/k8s/base/config-server-deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: config-server + name: config-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: config-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: config-server + spec: + containers: + - image: IMAGE_TAG_CONFIG_SERVER + name: config-server + ports: + - containerPort: 8888 + resources: {} + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/config-server-service.yaml b/k8s/base/config-server-service.yaml new file mode 100644 index 0000000000..e990afb1dc --- /dev/null +++ b/k8s/base/config-server-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: config-server + name: config-server +spec: + ports: + - name: "8888" + port: 8888 + targetPort: 8888 + selector: + io.kompose.service: config-server +status: + loadBalancer: {} diff --git a/k8s/base/customers-service-deployment.yaml b/k8s/base/customers-service-deployment.yaml new file mode 100644 index 0000000000..f4eb9dc892 --- /dev/null +++ b/k8s/base/customers-service-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: customers-service + name: customers-service +spec: + replicas: 2 + selector: + matchLabels: + io.kompose.service: customers-service + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: customers-service + spec: + containers: + - image: IMAGE_TAG_CUSTOMERS_SERVICE + name: customers-service + ports: + - containerPort: 8081 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/customers-service-ingress.yaml b/k8s/base/customers-service-ingress.yaml new file mode 100644 index 0000000000..716a7a6945 --- /dev/null +++ b/k8s/base/customers-service-ingress.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: customers-service + name: customers-service +spec: + rules: + - host: petclinic.clarusway.us + http: + paths: + - backend: + serviceName: customers-service + servicePort: 8081 +status: + loadBalancer: {} diff --git a/k8s/base/customers-service-service.yaml b/k8s/base/customers-service-service.yaml new file mode 100644 index 0000000000..aac4e3c552 --- /dev/null +++ b/k8s/base/customers-service-service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: customers-service + name: customers-service +spec: + ports: + - name: "8081" + port: 8081 + targetPort: 8081 + selector: + io.kompose.service: customers-service +status: + loadBalancer: {} diff --git a/k8s/base/discovery-server-deployment.yaml b/k8s/base/discovery-server-deployment.yaml new file mode 100644 index 0000000000..cb38b77ef2 --- /dev/null +++ b/k8s/base/discovery-server-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: discovery-server + name: discovery-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: discovery-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: discovery-server + spec: + containers: + - image: IMAGE_TAG_DISCOVERY_SERVER + name: discovery-server + ports: + - containerPort: 8761 + resources: {} + initContainers: + - name: init-config-server + image: busybox + command: ['sh', '-c', 'until nc -z config-server:8888; do echo waiting for config-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/discovery-server-service.yaml b/k8s/base/discovery-server-service.yaml new file mode 100644 index 0000000000..071e97ad1f --- /dev/null +++ b/k8s/base/discovery-server-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: discovery-server + name: discovery-server +spec: + ports: + - name: "8761" + port: 8761 + targetPort: 8761 + selector: + io.kompose.service: discovery-server +status: + loadBalancer: {} diff --git a/k8s/base/grafana-server-deployment.yaml b/k8s/base/grafana-server-deployment.yaml new file mode 100644 index 0000000000..ef95843478 --- /dev/null +++ b/k8s/base/grafana-server-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: grafana-server + name: grafana-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: grafana-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: grafana-server + spec: + containers: + - image: IMAGE_TAG_GRAFANA_SERVICE + name: grafana-server + ports: + - containerPort: 3000 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/grafana-server-service.yaml b/k8s/base/grafana-server-service.yaml new file mode 100644 index 0000000000..fabc03aedf --- /dev/null +++ b/k8s/base/grafana-server-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: grafana-server + name: grafana-server +spec: + ports: + - name: "3000" + port: 3000 + targetPort: 3000 + selector: + io.kompose.service: grafana-server +status: + loadBalancer: {} diff --git a/k8s/base/hystrix-dashboard-deployment.yaml b/k8s/base/hystrix-dashboard-deployment.yaml new file mode 100644 index 0000000000..2a7c6df14f --- /dev/null +++ b/k8s/base/hystrix-dashboard-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: hystrix-dashboard + name: hystrix-dashboard +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: hystrix-dashboard + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: hystrix-dashboard + spec: + containers: + - image: IMAGE_TAG_HYSTRIX_DASHBOARD + name: hystrix-dashboard + ports: + - containerPort: 7979 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/hystrix-dashboard-service.yaml b/k8s/base/hystrix-dashboard-service.yaml new file mode 100644 index 0000000000..50c22dc7c2 --- /dev/null +++ b/k8s/base/hystrix-dashboard-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: hystrix-dashboard + name: hystrix-dashboard +spec: + ports: + - name: "7979" + port: 7979 + targetPort: 7979 + selector: + io.kompose.service: hystrix-dashboard +status: + loadBalancer: {} diff --git a/k8s/base/kustomization-template.yml b/k8s/base/kustomization-template.yml new file mode 100644 index 0000000000..dbbe312b06 --- /dev/null +++ b/k8s/base/kustomization-template.yml @@ -0,0 +1,49 @@ +resources: +- admin-server-deployment.yaml +- api-gateway-deployment.yaml +- config-server-deployment.yaml +- customers-service-deployment.yaml +- discovery-server-deployment.yaml +- grafana-server-deployment.yaml +- hystrix-dashboard-deployment.yaml +- prometheus-server-deployment.yaml +- tracing-server-deployment.yaml +- vets-service-deployment.yaml +- visits-service-deployment.yaml +- admin-server-service.yaml +- api-gateway-service.yaml +- config-server-service.yaml +- customers-service-service.yaml +- discovery-server-service.yaml +- grafana-server-service.yaml +- hystrix-dashboard-service.yaml +- prometheus-server-service.yaml +- tracing-server-service.yaml +- vets-service-service.yaml +- visits-service-service.yaml +- api-gateway-ingress.yaml +- customers-service-ingress.yaml +- vets-service-ingress.yaml +- visits-service-ingress.yaml + +images: +- name: IMAGE_TAG_CONFIG_SERVER + newName: "${IMAGE_TAG_CONFIG_SERVER}" +- name: IMAGE_TAG_DISCOVERY_SERVER + newName: "${IMAGE_TAG_DISCOVERY_SERVER}" +- name: IMAGE_TAG_CUSTOMERS_SERVICE + newName: "${IMAGE_TAG_CUSTOMERS_SERVICE}" +- name: IMAGE_TAG_VISITS_SERVICE + newName: "${IMAGE_TAG_VISITS_SERVICE}" +- name: IMAGE_TAG_VETS_SERVICE + newName: "${IMAGE_TAG_VETS_SERVICE}" +- name: IMAGE_TAG_API_GATEWAY + newName: "${IMAGE_TAG_API_GATEWAY}" +- name: IMAGE_TAG_ADMIN_SERVER + newName: "${IMAGE_TAG_ADMIN_SERVER}" +- name: IMAGE_TAG_HYSTRIX_DASHBOARD + newName: "${IMAGE_TAG_HYSTRIX_DASHBOARD}" +- name: IMAGE_TAG_GRAFANA_SERVICE + newName: "${IMAGE_TAG_GRAFANA_SERVICE}" +- name: IMAGE_TAG_PROMETHEUS_SERVICE + newName: "${IMAGE_TAG_PROMETHEUS_SERVICE}" \ No newline at end of file diff --git a/k8s/base/kustomization.yml b/k8s/base/kustomization.yml new file mode 100644 index 0000000000..1fcd183677 --- /dev/null +++ b/k8s/base/kustomization.yml @@ -0,0 +1,49 @@ +resources: +- admin-server-deployment.yaml +- api-gateway-deployment.yaml +- config-server-deployment.yaml +- customers-service-deployment.yaml +- discovery-server-deployment.yaml +- grafana-server-deployment.yaml +- hystrix-dashboard-deployment.yaml +- prometheus-server-deployment.yaml +- tracing-server-deployment.yaml +- vets-service-deployment.yaml +- visits-service-deployment.yaml +- admin-server-service.yaml +- api-gateway-service.yaml +- config-server-service.yaml +- customers-service-service.yaml +- discovery-server-service.yaml +- grafana-server-service.yaml +- hystrix-dashboard-service.yaml +- prometheus-server-service.yaml +- tracing-server-service.yaml +- vets-service-service.yaml +- visits-service-service.yaml +- api-gateway-ingress.yaml +- customers-service-ingress.yaml +- vets-service-ingress.yaml +- visits-service-ingress.yaml + +images: +- name: IMAGE_TAG_CONFIG_SERVER + newName: "testing-image-1" +- name: IMAGE_TAG_DISCOVERY_SERVER + newName: "testing-image-2" +- name: IMAGE_TAG_CUSTOMERS_SERVICE + newName: "testing-image-3" +- name: IMAGE_TAG_VISITS_SERVICE + newName: "testing-image-4" +- name: IMAGE_TAG_VETS_SERVICE + newName: "testing-image-5" +- name: IMAGE_TAG_API_GATEWAY + newName: "testing-image-6" +- name: IMAGE_TAG_ADMIN_SERVER + newName: "testing-image-7" +- name: IMAGE_TAG_HYSTRIX_DASHBOARD + newName: "testing-image-8" +- name: IMAGE_TAG_GRAFANA_SERVICE + newName: "testing-image-9" +- name: IMAGE_TAG_PROMETHEUS_SERVICE + newName: "testing-image-10" \ No newline at end of file diff --git a/k8s/base/prometheus-server-deployment.yaml b/k8s/base/prometheus-server-deployment.yaml new file mode 100644 index 0000000000..ffacc07f31 --- /dev/null +++ b/k8s/base/prometheus-server-deployment.yaml @@ -0,0 +1,41 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: prometheus-server + name: prometheus-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: prometheus-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: prometheus-server + spec: + containers: + - image: IMAGE_TAG_PROMETHEUS_SERVICE + name: prometheus-server + ports: + - containerPort: 9090 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/prometheus-server-service.yaml b/k8s/base/prometheus-server-service.yaml new file mode 100644 index 0000000000..105d6aa454 --- /dev/null +++ b/k8s/base/prometheus-server-service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: prometheus-server + name: prometheus-server +spec: + ports: + - name: "9091" + port: 9091 + targetPort: 9090 + selector: + io.kompose.service: prometheus-server +status: + loadBalancer: {} diff --git a/k8s/base/tracing-server-deployment.yaml b/k8s/base/tracing-server-deployment.yaml new file mode 100644 index 0000000000..563293c718 --- /dev/null +++ b/k8s/base/tracing-server-deployment.yaml @@ -0,0 +1,36 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: tracing-server + name: tracing-server +spec: + replicas: 1 + selector: + matchLabels: + io.kompose.service: tracing-server + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: tracing-server + spec: + containers: + - env: + - name: JAVA_OPTS + value: -XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom + image: openzipkin/zipkin + name: tracing-server + ports: + - containerPort: 9411 + resources: {} + restartPolicy: Always +status: {} diff --git a/k8s/base/tracing-server-service.yaml b/k8s/base/tracing-server-service.yaml new file mode 100644 index 0000000000..7bdabd2e6a --- /dev/null +++ b/k8s/base/tracing-server-service.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: tracing-server + name: tracing-server +spec: + ports: + - name: "9411" + port: 9411 + targetPort: 9411 + selector: + io.kompose.service: tracing-server +status: + loadBalancer: {} diff --git a/k8s/base/vets-service-deployment.yaml b/k8s/base/vets-service-deployment.yaml new file mode 100644 index 0000000000..4e29396e6f --- /dev/null +++ b/k8s/base/vets-service-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: vets-service + name: vets-service +spec: + replicas: 2 + selector: + matchLabels: + io.kompose.service: vets-service + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: vets-service + spec: + containers: + - image: IMAGE_TAG_VETS_SERVICE + name: vets-service + ports: + - containerPort: 8083 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/vets-service-ingress.yaml b/k8s/base/vets-service-ingress.yaml new file mode 100644 index 0000000000..06a1894096 --- /dev/null +++ b/k8s/base/vets-service-ingress.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: vets-service + name: vets-service +spec: + rules: + - host: petclinic.clarusway.us + http: + paths: + - backend: + serviceName: vets-service + servicePort: 8083 +status: + loadBalancer: {} diff --git a/k8s/base/vets-service-service.yaml b/k8s/base/vets-service-service.yaml new file mode 100644 index 0000000000..6444738246 --- /dev/null +++ b/k8s/base/vets-service-service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: vets-service + name: vets-service +spec: + ports: + - name: "8083" + port: 8083 + targetPort: 8083 + selector: + io.kompose.service: vets-service +status: + loadBalancer: {} diff --git a/k8s/base/visits-service-deployment.yaml b/k8s/base/visits-service-deployment.yaml new file mode 100644 index 0000000000..5e48933d2d --- /dev/null +++ b/k8s/base/visits-service-deployment.yaml @@ -0,0 +1,43 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: visits-service + name: visits-service +spec: + replicas: 2 + selector: + matchLabels: + io.kompose.service: visits-service + strategy: {} + template: + metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: visits-service + spec: + containers: + - image: IMAGE_TAG_VISITS_SERVICE + name: visits-service + ports: + - containerPort: 8082 + resources: {} + initContainers: + - name: init-discovery-server + image: busybox + command: ['sh', '-c', 'until nc -z discovery-server:8761; do echo waiting for discovery-server; sleep 2; done;'] + imagePullSecrets: + - name: regcred + restartPolicy: Always +status: {} diff --git a/k8s/base/visits-service-ingress.yaml b/k8s/base/visits-service-ingress.yaml new file mode 100644 index 0000000000..9d7378d62d --- /dev/null +++ b/k8s/base/visits-service-ingress.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: visits-service + name: visits-service +spec: + rules: + - host: petclinic.clarusway.us + http: + paths: + - backend: + serviceName: visits-service + servicePort: 8082 +status: + loadBalancer: {} diff --git a/k8s/base/visits-service-service.yaml b/k8s/base/visits-service-service.yaml new file mode 100644 index 0000000000..730910dd3c --- /dev/null +++ b/k8s/base/visits-service-service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + kompose.cmd: kompose convert -f docker-compose.yml -o base + kompose.image-pull-secret: regcred + kompose.service.expose: petclinic.clarusway.us + kompose.version: 1.22.0 (955b78124) + creationTimestamp: null + labels: + io.kompose.service: visits-service + name: visits-service +spec: + ports: + - name: "8082" + port: 8082 + targetPort: 8082 + selector: + io.kompose.service: visits-service +status: + loadBalancer: {} diff --git a/k8s/docker-compose.yml b/k8s/docker-compose.yml new file mode 100644 index 0000000000..f31dbad415 --- /dev/null +++ b/k8s/docker-compose.yml @@ -0,0 +1,80 @@ +version: '3' +services: + config-server: + image: IMAGE_TAG_CONFIG_SERVER + ports: + - 8888:8888 + labels: + kompose.image-pull-secret: "regcred" + discovery-server: + image: IMAGE_TAG_DISCOVERY_SERVER + ports: + - 8761:8761 + labels: + kompose.image-pull-secret: "regcred" + customers-service: + image: IMAGE_TAG_CUSTOMERS_SERVICE + deploy: + replicas: 2 + ports: + - 8081:8081 + labels: + kompose.image-pull-secret: "regcred" + kompose.service.expose: "petclinic.clarusway.us" + visits-service: + image: IMAGE_TAG_VISITS_SERVICE + deploy: + replicas: 2 + ports: + - 8082:8082 + labels: + kompose.image-pull-secret: "regcred" + kompose.service.expose: "petclinic.clarusway.us" + vets-service: + image: IMAGE_TAG_VETS_SERVICE + deploy: + replicas: 2 + ports: + - 8083:8083 + labels: + kompose.image-pull-secret: "regcred" + kompose.service.expose: "petclinic.clarusway.us" + api-gateway: + image: IMAGE_TAG_API_GATEWAY + deploy: + replicas: 2 + ports: + - 8080:8080 + labels: + kompose.image-pull-secret: "regcred" + kompose.service.expose: "petclinic.clarusway.us" + tracing-server: + image: openzipkin/zipkin + environment: + - JAVA_OPTS=-XX:+UnlockExperimentalVMOptions -Djava.security.egd=file:/dev/./urandom + ports: + - 9411:9411 + admin-server: + image: IMAGE_TAG_ADMIN_SERVER + ports: + - 9090:9090 + labels: + kompose.image-pull-secret: "regcred" + hystrix-dashboard: + image: IMAGE_TAG_HYSTRIX_DASHBOARD + ports: + - 7979:7979 + labels: + kompose.image-pull-secret: "regcred" + grafana-server: + image: IMAGE_TAG_GRAFANA_SERVICE + ports: + - 3000:3000 + labels: + kompose.image-pull-secret: "regcred" + prometheus-server: + image: IMAGE_TAG_PROMETHEUS_SERVICE + ports: + - 9091:9090 + labels: + kompose.image-pull-secret: "regcred" \ No newline at end of file diff --git a/k8s/prod/kustomization.yml b/k8s/prod/kustomization.yml new file mode 100644 index 0000000000..0734bdc214 --- /dev/null +++ b/k8s/prod/kustomization.yml @@ -0,0 +1,6 @@ +# kustomization.yml +namespace: "petclinic-prod-ns" +bases: +- ../base +patches: +- replica-count.yml \ No newline at end of file diff --git a/k8s/prod/replica-count.yml b/k8s/prod/replica-count.yml new file mode 100644 index 0000000000..74cd993bb1 --- /dev/null +++ b/k8s/prod/replica-count.yml @@ -0,0 +1,7 @@ +# replica-count.yml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-gateway +spec: + replicas: 5 \ No newline at end of file diff --git a/k8s/staging/kustomization.yml b/k8s/staging/kustomization.yml new file mode 100644 index 0000000000..80d4c1be96 --- /dev/null +++ b/k8s/staging/kustomization.yml @@ -0,0 +1,6 @@ +# kustomization.yml +namespace: "petclinic-staging-ns" +bases: +- ../base +patches: +- replica-count.yml \ No newline at end of file diff --git a/k8s/staging/replica-count.yml b/k8s/staging/replica-count.yml new file mode 100644 index 0000000000..e9a4bb5edf --- /dev/null +++ b/k8s/staging/replica-count.yml @@ -0,0 +1,7 @@ +# replica-count.yml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: api-gateway +spec: + replicas: 3 \ No newline at end of file diff --git a/package-with-mvn-wrapper.sh b/package-with-mvn-wrapper.sh new file mode 100644 index 0000000000..ab98051854 --- /dev/null +++ b/package-with-mvn-wrapper.sh @@ -0,0 +1,2 @@ +# package-with-mvn-wrapper.sh +./mvnw clean package \ No newline at end of file diff --git a/pom.xml b/pom.xml index da42b9ce94..e1ddfe6dfb 100644 --- a/pom.xml +++ b/pom.xml @@ -129,6 +129,26 @@ false + + org.jacoco + jacoco-maven-plugin + 0.8.2 + + + + prepare-agent + + + + + report + test + + report + + + + diff --git a/selenium-jobs/dummy_selenium_test_headless.py b/selenium-jobs/dummy_selenium_test_headless.py new file mode 100644 index 0000000000..05d9c12dcc --- /dev/null +++ b/selenium-jobs/dummy_selenium_test_headless.py @@ -0,0 +1,14 @@ +from selenium import webdriver +chrome_options = webdriver.ChromeOptions() +chrome_options.add_argument("headless") +chrome_options.add_argument("no-sandbox") +chrome_options.add_argument("disable-dev-shm-usage") +driver = webdriver.Chrome(options=chrome_options) +base_url = "https://www.google.com/" +driver.get(base_url) +source = driver.page_source +if "I'm Feeling Lucky" in source: + print("Test passed") +else: + print("Test failed") +driver.close() \ No newline at end of file diff --git a/selenium-jobs/test_owners_all_headless.py b/selenium-jobs/test_owners_all_headless.py new file mode 100644 index 0000000000..578872b94d --- /dev/null +++ b/selenium-jobs/test_owners_all_headless.py @@ -0,0 +1,29 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from time import sleep +import os +# Set chrome options for working with headless mode (no screen) +chrome_options = webdriver.ChromeOptions() +chrome_options.add_argument("headless") +chrome_options.add_argument("no-sandbox") +chrome_options.add_argument("disable-dev-shm-usage") +# Update webdriver instance of chrome-driver with adding chrome options +driver = webdriver.Chrome(options=chrome_options) +# Connect to the application +APP_IP = os.environ['MASTER_PUBLIC_IP'] +url = "http://"+APP_IP.strip()+":8080/" +print(url) +driver.get(url) +owners_link = driver.find_element_by_link_text("OWNERS") +owners_link.click() +sleep(2) +all_link = driver.find_element_by_link_text("ALL") +all_link.click() +sleep(2) +# Verify that table loaded +sleep(1) +verify_table = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "table"))) +print("Table loaded") +driver.quit() \ No newline at end of file diff --git a/selenium-jobs/test_owners_register_headless.py b/selenium-jobs/test_owners_register_headless.py new file mode 100644 index 0000000000..85135d98cf --- /dev/null +++ b/selenium-jobs/test_owners_register_headless.py @@ -0,0 +1,46 @@ +from selenium import webdriver +from selenium.webdriver.common.keys import Keys +from time import sleep +import random +import os +# Set chrome options for working with headless mode (no screen) +chrome_options = webdriver.ChromeOptions() +chrome_options.add_argument("headless") +chrome_options.add_argument("no-sandbox") +chrome_options.add_argument("disable-dev-shm-usage") +# Update webdriver instance of chrome-driver with adding chrome options +driver = webdriver.Chrome(options=chrome_options) +# Connect to the application +APP_IP = os.environ['MASTER_PUBLIC_IP'] +url = "http://"+APP_IP.strip()+":8080/" +print(url) +driver.get(url) +owners_link = driver.find_element_by_link_text("OWNERS") +owners_link.click() +sleep(2) +all_link = driver.find_element_by_link_text("REGISTER") +all_link.click() +sleep(2) +# Register new Owner to Petclinic App +fn_field = driver.find_element_by_name('firstName') +fn = 'Callahan' + str(random.randint(0, 100)) +fn_field.send_keys(fn) +fn_field = driver.find_element_by_name('lastName') +fn_field.send_keys('Clarusway') +fn_field = driver.find_element_by_name('address') +fn_field.send_keys('Ridge Corp. Street') +fn_field = driver.find_element_by_name('city') +fn_field.send_keys('McLean') +fn_field = driver.find_element_by_name('telephone') +fn_field.send_keys('+1230576803') +fn_field.send_keys(Keys.ENTER) +# Wait 1 second to get updated Owner List +sleep(2) +# Verify that new user is added to Owner List +if fn in driver.page_source: + print(fn, 'is added and found in the Owners Table') + print("Test Passed") +else: + print(fn, 'is not found in the Owners Table') + print("Test Failed") +driver.quit() \ No newline at end of file diff --git a/selenium-jobs/test_veterinarians_headless.py b/selenium-jobs/test_veterinarians_headless.py new file mode 100644 index 0000000000..fc6958c3cd --- /dev/null +++ b/selenium-jobs/test_veterinarians_headless.py @@ -0,0 +1,25 @@ +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.support.ui import WebDriverWait +from selenium.webdriver.support import expected_conditions as EC +from time import sleep +import os +# Set chrome options for working with headless mode (no screen) +chrome_options = webdriver.ChromeOptions() +chrome_options.add_argument("headless") +chrome_options.add_argument("no-sandbox") +chrome_options.add_argument("disable-dev-shm-usage") +# Update webdriver instance of chrome-driver with adding chrome options +driver = webdriver.Chrome(options=chrome_options) +# Connect to the application +APP_IP = os.environ['MASTER_PUBLIC_IP'] +url = "http://"+APP_IP.strip()+":8080/" +print(url) +driver.get(url) +vet_link = driver.find_element_by_link_text("VETERINARIANS") +vet_link.click() +# Verify that table loaded +sleep(1) +verify_table = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "table"))) +print("Table loaded") +driver.quit() \ No newline at end of file diff --git a/spring-petclinic-admin-server/Dockerfile b/spring-petclinic-admin-server/Dockerfile new file mode 100644 index 0000000000..f00c9731a5 --- /dev/null +++ b/spring-petclinic-admin-server/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=9090 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-api-gateway/Dockerfile b/spring-petclinic-api-gateway/Dockerfile new file mode 100644 index 0000000000..c5820520a5 --- /dev/null +++ b/spring-petclinic-api-gateway/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8080 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-config-server/Dockerfile b/spring-petclinic-config-server/Dockerfile new file mode 100644 index 0000000000..365b88e105 --- /dev/null +++ b/spring-petclinic-config-server/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8888 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-customers-service/Dockerfile b/spring-petclinic-customers-service/Dockerfile new file mode 100644 index 0000000000..b1c1e0c8cd --- /dev/null +++ b/spring-petclinic-customers-service/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8081 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/model/PetTest.java b/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/model/PetTest.java new file mode 100644 index 0000000000..2a6380fbcf --- /dev/null +++ b/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/model/PetTest.java @@ -0,0 +1,39 @@ +package org.springframework.samples.petclinic.customers.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Date; + +import org.junit.jupiter.api.Test; +public class PetTest { + @Test + public void testGetName(){ + //Arrange + Pet pet = new Pet(); + //Act + pet.setName("Fluffy"); + //Assert + assertEquals("Fluffy", pet.getName()); + } + @Test + public void testGetOwner(){ + //Arrange + Pet pet = new Pet(); + Owner owner = new Owner(); + owner.setFirstName("Call"); + //Act + pet.setOwner(owner); + //Assert + assertEquals("Call", pet.getOwner().getFirstName()); + } + @Test + public void testBirthDate(){ + //Arrange + Pet pet = new Pet(); + Date bd = new Date(); + //Act + pet.setBirthDate(bd); + //Assert + assertEquals(bd,pet.getBirthDate()); + } +} diff --git a/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/PetResourceTest.java b/spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/web/PetResourceTest.java similarity index 100% rename from spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/PetResourceTest.java rename to spring-petclinic-customers-service/src/test/java/org/springframework/samples/petclinic/customers/web/web/PetResourceTest.java diff --git a/spring-petclinic-discovery-server/Dockerfile b/spring-petclinic-discovery-server/Dockerfile new file mode 100644 index 0000000000..4b2ef3dd87 --- /dev/null +++ b/spring-petclinic-discovery-server/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8761 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-hystrix-dashboard/Dockerfile b/spring-petclinic-hystrix-dashboard/Dockerfile new file mode 100644 index 0000000000..db170a937c --- /dev/null +++ b/spring-petclinic-hystrix-dashboard/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=7979 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-vets-service/Dockerfile b/spring-petclinic-vets-service/Dockerfile new file mode 100644 index 0000000000..40df3f0817 --- /dev/null +++ b/spring-petclinic-vets-service/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8083 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/spring-petclinic-visits-service/Dockerfile b/spring-petclinic-visits-service/Dockerfile new file mode 100644 index 0000000000..09c9126fbd --- /dev/null +++ b/spring-petclinic-visits-service/Dockerfile @@ -0,0 +1,11 @@ +FROM openjdk:11-jre +ARG DOCKERIZE_VERSION=v0.6.1 +ARG EXPOSED_PORT=8082 +ENV SPRING_PROFILES_ACTIVE docker +ADD https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-alpine-linux-amd64-${DOCKERIZE_VERSION}.tar.gz dockerize.tar.gz +RUN tar xzf dockerize.tar.gz +RUN chmod +x dockerize +ADD ./target/*.jar /app.jar +EXPOSE ${EXPOSED_PORT} +ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ] + diff --git a/test-local-deployment.sh b/test-local-deployment.sh new file mode 100644 index 0000000000..56b0279f33 --- /dev/null +++ b/test-local-deployment.sh @@ -0,0 +1,2 @@ +# test-local-deployment +docker-compose -f docker-compose-local.yml up \ No newline at end of file