diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0f558af --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +docker-data +*.tar +ansible +sonar-project.properties +.git +docker-compose.yml +.env +vendor \ No newline at end of file diff --git a/.env.example b/.env.local similarity index 54% rename from .env.example rename to .env.local index 031862b..2e4ef98 100644 --- a/.env.example +++ b/.env.local @@ -1,11 +1,11 @@ -APP_ENV=local +APP_ENV=testlaravel APP_DEBUG=true -APP_KEY=SomeRandomString +APP_KEY=base64:oPD/hrRXGvA1hydZp17JAQH2PnflMgp4P5OMWoldWTM= -DB_HOST=localhost -DB_DATABASE=homestead -DB_USERNAME=homestead -DB_PASSWORD=secret +DB_HOST=db +DB_DATABASE=laravel +DB_USERNAME=root +DB_PASSWORD=your_mysql_root_password CACHE_DRIVER=file SESSION_DRIVER=file @@ -21,3 +21,6 @@ MAIL_PORT=2525 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null + +JAEGER_HOST: jaeger +JAEGER_PORT: 6831 diff --git a/.gitignore b/.gitignore index 6ee6a1c..5f8e979 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,5 @@ Homestead.yaml Homestead.json .env public/images -storage/ .DS_Store +docker-data \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..68ec17d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,67 @@ +FROM php:7.2-fpm + +# Set working directory +WORKDIR /var/www + +# Install dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + mysql-client \ + libpng-dev \ + libjpeg62-turbo-dev \ + libfreetype6-dev \ + locales \ + zip \ + jpegoptim optipng pngquant gifsicle \ + vim \ + unzip \ + git \ + curl \ + libgmp-dev + +# Clear cache +RUN apt-get clean && rm -rf /var/lib/apt/lists/* + +## Opencensus +RUN pecl install opencensus-alpha + +RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/ + +# Install extensions +RUN docker-php-ext-install pdo_mysql \ + mbstring \ + zip \ + exif \ + pcntl \ + gd \ + sockets \ + gmp + +# Install composer +RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer + +# Add user for laravel application +RUN groupadd -g 1000 www +RUN useradd -u 1000 -ms /bin/bash -g www www + +# Copy composer.lock and composer.json +COPY composer.lock composer.json /var/www/ + +RUN composer install --prefer-source --no-dev --no-autoloader --no-scripts --no-progress --no-suggest + +# Copy existing application directory contents +COPY . /var/www + +RUN composer install --prefer-dist --no-dev -o + +# Copy existing application directory permissions +COPY --chown=www:www . /var/www + +ADD ./docker/php/local.ini /usr/local/etc/php/conf.d + +# Change current user to www +USER www + +# Expose port 9000 and start php-fpm server +EXPOSE 9000 +CMD ["php-fpm"] \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..5c47e8c --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,170 @@ +def getdockertag(){ + return "${env.GIT_BRANCH}".replace("/",".") + "."+"${env.BUILD_ID}" +} +pipeline { + agent any + environment { + DOCKER_REGISTRY = "varunpalekar1/php-test" + DOCKER_TAG = getdockertag() + } + stages { + stage('Build') { + steps { + script { + echo "install compose.json" + sh 'composer install --prefer-source' + sh 'printenv' + dir('ansible') { + sh 'ansible-galaxy install -r requirements.yml' + } + } + } + } + stage('UnitTest') { + environment { + DB_HOST = "localhost" + DB_DATABASE = "laravel_test" + DB_USERNAME = "laravel_test" + DB_PASSWORD = "my_pass" + } + steps { + script { + try{ + echo "Running Test cases" + sh './vendor/bin/phpunit --colors tests --log-junit reports/junit.xml' + } + catch(Exception e){ + if ( GIT_BRANCH ==~ /.*master|.*hotfix\/.*|.*release\/.*/ ) + error "Test case failed" + else + echo "Skipped test if from personal or feature branch" + } + try{ + echo "Running Test code coverage" + sh './vendor/bin/phpunit --coverage-clover reports/codeCoverage.xml' + } + catch(Exception e){ + if ( GIT_BRANCH ==~ /.*master|.*hotfix\/.*|.*release\/.*/ ) + error "Code coverage failed" + else + echo "Skipped code coverage if from personal or feature branch" + } + } + } + } + stage('CodeAnalysis') { + when { + expression { + GIT_BRANCH ==~ /.*master|.*feature\/.*|.*develop|.*hotfix\/.*|.*release\/.*/ + } + } + steps { + script { + scannerHome = tool name: 'sonar-scanner', type: 'hudson.plugins.sonar.SonarRunnerInstallation' + } + withSonarQubeEnv('sonarqube.io') { + sh "${scannerHome}/bin/sonar-scanner -Dsonar.branch.name=${GIT_BRANCH} -Dsonar.projectKey=varunpalekar_php-test -Dsonar.organization=varunpalekar-github" + } + } + } + stage('DockerPush') { + when { + expression { + GIT_BRANCH ==~ /.*master|.*release\/.*|.*develop|.*hotfix\/.*/ + } + } + steps { + script{ + docker.withRegistry('', 'public-docker-hub') { + + def customImage = docker.build("${env.DOCKER_REGISTRY}:${env.DOCKER_TAG}") + customImage.push() + + if ( GIT_BRANCH ==~ /.*master|.*hotfix\/.*|.*release\/.*/ ) + customImage.push('latest') + } + } + } + } + stage('Deploy_Dev') { + when { + expression { + GIT_BRANCH ==~ /.*develop/ + } + } + steps { + script{ + echo "Deploy application on developmment environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-dev', playbook: 'playbook.yml', extraVars: [ + deployment_app_image: "${env.DOCKER_REGISTRY}:${env.DOCKER_TAG}" + ] + } + } + + input message: "Do you want to run migration?" + + script{ + echo "Deploy application on developmment environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-dev', playbook: 'playbook.yml', tags: 'migration' + } + } + + input message: "Do you want to run seeding?" + + script{ + echo "Deploy application on developmment environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-dev', playbook: 'playbook.yml', tags: 'seeding' + } + } + } + } + + stage('Undeploy_Dev'){ + when { + expression { + GIT_BRANCH ==~ /.*develop/ + } + } + // timeout(time:5, unit:'DAYS') { + // input message:'Approve deployment?', submitter: 'it-ops' + // } + steps { + input message: "Do you want to undeploy DEV?" + script { + echo "Undeploy application on developmment environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-dev', playbook: 'playbook.yml', tags: 'undeploy' + } + } + } + } + stage('Deploy_Prod') { + when { + expression { + GIT_BRANCH ==~ /.*master|.*release\/.*|.*hotfix\/.*/ + } + } + steps { + input message: "Do you want to proceed for production deployment?" + script{ + echo "Deploy application on stage environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-prod', playbook: 'playbook.yml', credentialsId: 'ansible-hospice-prod' + } + } + + input message: "Do you want to proceed for production migration?" + script{ + echo "Deploy application on stage environment" + dir("ansible") { + ansiblePlaybook installation: 'ansible', inventory: 'hosts-prod', playbook: 'playbook.yml', tags: 'migration', credentialsId: 'ansible-hospice-prod' + } + } + } + } + + } +} diff --git a/ansible/.gitignore b/ansible/.gitignore new file mode 100644 index 0000000..db40f8a --- /dev/null +++ b/ansible/.gitignore @@ -0,0 +1,2 @@ +*-console.log +.vagrant \ No newline at end of file diff --git a/ansible/Vagrantfile b/ansible/Vagrantfile new file mode 100644 index 0000000..9f13cb4 --- /dev/null +++ b/ansible/Vagrantfile @@ -0,0 +1,48 @@ +servers=[ + { + :hostname => "dev", + :ip => "192.168.94.41", + :box => "ubuntu/bionic64", + :ram => 1024, + :cpu => 1 + }, + { + :hostname => "prod", + :ip => "192.168.94.42", + :box => "ubuntu/bionic64", + :ram => 1024, + :cpu => 1 + } +] + +$initialize = <<-SCRIPT +cat /vagrant/vagrant/id_rsa.pub >> /home/vagrant/.ssh/authorized_keys +apt-get update && apt install -y python +SCRIPT + +Vagrant.configure("2") do |config| + + if Vagrant.has_plugin?("vagrant-hostmanager") + config.hostmanager.enabled = true + config.hostmanager.manage_guest = true + end + + if Vagrant.has_plugin?("vagrant-cachier") + config.cache.scope = :box + end + + config.vm.provision "shell", inline: $initialize + + servers.each do |machine| + config.vm.define machine[:hostname] do |node| + node.vm.box = machine[:box] + node.vm.hostname = machine[:hostname] + node.vm.network "private_network", ip: machine[:ip] + node.vm.provider "virtualbox" do |vb| + vb.memory = machine[:ram] + vb.cpus = machine[:cpu] + vb.linked_clone = true + end + end + end + end \ No newline at end of file diff --git a/ansible/hosts-dev b/ansible/hosts-dev new file mode 100644 index 0000000..cf8baf9 --- /dev/null +++ b/ansible/hosts-dev @@ -0,0 +1,5 @@ +[hospice] +192.168.94.41 ansible_user=vagrant + +[all:vars] +env=dev \ No newline at end of file diff --git a/ansible/hosts-prod b/ansible/hosts-prod new file mode 100644 index 0000000..8c6606c --- /dev/null +++ b/ansible/hosts-prod @@ -0,0 +1,5 @@ +[hospice] +192.168.94.42 ansible_user=vagrant + +[all:vars] +env=prod \ No newline at end of file diff --git a/ansible/playbook.retry b/ansible/playbook.retry new file mode 100644 index 0000000..2cbe3e8 --- /dev/null +++ b/ansible/playbook.retry @@ -0,0 +1 @@ +192.168.94.41 diff --git a/ansible/playbook.yml b/ansible/playbook.yml new file mode 100644 index 0000000..f8ca9fb --- /dev/null +++ b/ansible/playbook.yml @@ -0,0 +1,11 @@ +--- +- hosts: all + become: yes + vars_files: + - "vars/{{ env }}.yml" + roles: + - role: mysql + when: env == 'prod' + - role: docker + docker_install_compose: true + - role: deployment diff --git a/ansible/requirements.yml b/ansible/requirements.yml new file mode 100644 index 0000000..96a6516 --- /dev/null +++ b/ansible/requirements.yml @@ -0,0 +1,7 @@ +--- + +- name: docker + src: geerlingguy.docker + +- name: mysql + src: geerlingguy.mysql \ No newline at end of file diff --git a/ansible/roles/deployment/defaults/main.yml b/ansible/roles/deployment/defaults/main.yml new file mode 100644 index 0000000..c5cbed7 --- /dev/null +++ b/ansible/roles/deployment/defaults/main.yml @@ -0,0 +1,42 @@ +deployment_project_dir: '/data/hospice/docker_compose' + +deployment_webserver: + ports: + - "80" + - "443" + volumes: + - ./:/var/www + - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ + +deployment_app: + build: + context: . + dockerfile: Dockerfile + image: varun/laravel-php-fpm + environment: + APP_ENV: dev + APP_DEBUG: true + APP_KEY: base64:oPD/hrRXGvA1hydZp17JAQH2PnflMgp4P5OMWoldWTM= + + DB_HOST: db + DB_DATABASE: + DB_USERNAME: root + DB_PASSWORD: your_mysql_root_password + + JAEGER_HOST: jaeger + JAEGER_PORT: 6831 + JAEGER_ENABLE: "false" + + working_dir: /var/www + volumes: + - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini + +deployment_db: + volumes: + - ./docker-data/mysql:/var/lib/mysql + - ./docker/mysql/my.cnf:/etc/mysql/my.cnf + environment: + MYSQL_DATABASE: laravel + MYSQL_ROOT_PASSWORD: your_mysql_root_password + SERVICE_TAGS: dev + SERVICE_NAME: mysql \ No newline at end of file diff --git a/ansible/roles/deployment/tasks/deploy.yml b/ansible/roles/deployment/tasks/deploy.yml new file mode 100644 index 0000000..3daddfb --- /dev/null +++ b/ansible/roles/deployment/tasks/deploy.yml @@ -0,0 +1,46 @@ +--- + +- name: create project directory {{ deployment_project_dir }} + file: path={{ deployment_project_dir }} state=directory + +- name: push project code + synchronize: + src: "{{ playbook_dir }}/../{{ item }}" + dest: "{{ deployment_project_dir }}" + dirs: yes + rsync_opts: + - "--exclude=docker-data" + loop: + - public + - docker-compose.yml + - docker + +- name: create override docker-compose file + template: + src: docker-compose.yml.j2 + dest: "{{ deployment_project_dir }}/docker-compose.{{env}}.yml" + +- name: docker pull deployable image + docker_image: + name: "{{ deployment_app_image }}" + pull: yes + +- name: start project + docker_service: + project_src: "{{ deployment_project_dir }}" + build: no + files: + - docker-compose.yml + - "docker-compose.{{env}}.yml" + state: present + restarted: yes + register: deployment_service_out + +- name: get docker-port of webserver + shell: docker-compose -f docker-compose.yml -f docker-compose.{{env}}.yml port webserver 80 + args: + chdir: "{{ deployment_project_dir }}" + register: deployment_webserver_port + +- debug: + msg: "Webserver dynamic URL: http://{{ ansible_ssh_host }}:{{ deployment_webserver_port.stdout | regex_search('(?<=:).*') }}" diff --git a/ansible/roles/deployment/tasks/main.yml b/ansible/roles/deployment/tasks/main.yml new file mode 100644 index 0000000..b387efb --- /dev/null +++ b/ansible/roles/deployment/tasks/main.yml @@ -0,0 +1,35 @@ +--- + +- name: install required packages + package: + name: "{{ item }}" + loop: + - python-pip + +- name: install docker python module + pip: + name: "{{ item }}" + loop: + - docker + - docker-compose + +- name: Deploy-application + include_tasks: deploy.yml + +- name: Undeploy-application + include_tasks: undeploy.yml + tags: + - never + - undeploy + +- name: migration update + include_tasks: migration.yml + tags: + - never + - migration + +- name: seeding + include_tasks: seeding.yml + tags: + - never + - seeding \ No newline at end of file diff --git a/ansible/roles/deployment/tasks/migration.yml b/ansible/roles/deployment/tasks/migration.yml new file mode 100644 index 0000000..df776b8 --- /dev/null +++ b/ansible/roles/deployment/tasks/migration.yml @@ -0,0 +1,21 @@ + +- name: docker-compose exec migration + shell: "docker-compose -f docker-compose.yml -f docker-compose.{{env}}.yml exec -T app php artisan migrate" + args: + chdir: "{{ deployment_project_dir }}" + register: deployment_migration_output + loop: + - migrate + - status + tags: + - migration + +- debug: + msg: "{{ item.key }}: {{ item.value }}" + loop: + - key: "{{ deployment_migration_output.results[0].item }}" + value: "{{ deployment_migration_output.results[0].stdout }}" + - key: "{{deployment_migration_output.results[1].item}}" + value: "{{deployment_migration_output.results[1].stdout}}" + tags: + - migration \ No newline at end of file diff --git a/ansible/roles/deployment/tasks/seeding.yml b/ansible/roles/deployment/tasks/seeding.yml new file mode 100644 index 0000000..393dacf --- /dev/null +++ b/ansible/roles/deployment/tasks/seeding.yml @@ -0,0 +1,11 @@ +- name: docker-compose exec seeding + shell: "docker-compose -f docker-compose.yml -f docker-compose.{{env}}.yml exec -T app php artisan {{ item }}" + args: + chdir: "{{ deployment_project_dir }}" + register: deployment_seeding_out + loop: + - db:seed --class=UsersTableSeeder + - db:seed --class=PostsTableSeeder + - db:seed --class=PostsTableSeeder + tags: + - seeding diff --git a/ansible/roles/deployment/tasks/undeploy.yml b/ansible/roles/deployment/tasks/undeploy.yml new file mode 100644 index 0000000..65863d0 --- /dev/null +++ b/ansible/roles/deployment/tasks/undeploy.yml @@ -0,0 +1,18 @@ +--- + +- name: stop docker compose + docker_service: + project_src: "{{ deployment_project_dir }}" + files: + - docker-compose.yml + - "docker-compose.{{env}}.yml" + state: absent + tags: + - undeploy + +- name: delete project folder + file: + state: absent + path: "{{ deployment_project_dir }}" + tags: + - undeploy \ No newline at end of file diff --git a/ansible/roles/deployment/templates/docker-compose.yml.j2 b/ansible/roles/deployment/templates/docker-compose.yml.j2 new file mode 100644 index 0000000..2281f53 --- /dev/null +++ b/ansible/roles/deployment/templates/docker-compose.yml.j2 @@ -0,0 +1,84 @@ +version: "3" + +services: +{% if deployment_webserver %} + webserver: +{% if deployment_webserver.ports is defined %} + ports: +{% for val in deployment_webserver.ports %} + - {{ val }} +{% endfor %} +{% endif %} + +{% if deployment_webserver.volumes is defined %} + volumes: +{% for val in deployment_webserver.volumes %} + - {{ val }} +{% endfor %} +{% endif %} + +{% if deployment_webserver.environment is defined %} + environment: +{% for key, val in deployment_webserver.environment.iteritems() %} + {{ key }} : "{{ val }}" +{% endfor %} +{% endif %} +{% endif %} + +{% if deployment_app %} + # PHP-fpm server + app: +{% if deployment_app.ports is defined %} + ports: +{% for val in deployment_app.ports %} + - {{ val }} +{% endfor %} +{% endif %} + +{% if deployment_app.image is defined %} + image: {{ deployment_app.image }} +{% endif %} + +{% if deployment_app.volumes is defined %} + volumes: +{% for val in deployment_app.volumes %} + - {{ val }} +{% endfor %} +{% endif %} + +{% if deployment_app.environment is defined %} + environment: +{% for key, val in deployment_app.environment.iteritems() %} + {{ key }} : "{{ val }}" +{% endfor %} +{% endif %} +{% endif %} + +{% if deployment_db %} + ## MYSQL db + db: +{% if deployment_db.ports is defined %} + ports: +{% for val in deployment_db.ports %} + - {{ val }} +{% endfor %} +{% endif %} + +{% if deployment_db.volumes is defined %} + volumes: +{% for val in deployment_db.volumes %} + - {{ val }} +{% endfor %} +{% endif %} + image: mysql:5.7.22 + container_name: db + restart: unless-stopped + networks: + - app-network +{% if deployment_db.environment is defined %} + environment: +{% for key, val in deployment_db.environment.iteritems() %} + {{ key }} : "{{ val }}" +{% endfor %} +{% endif %} +{% endif %} \ No newline at end of file diff --git a/ansible/vagrant/id_rsa b/ansible/vagrant/id_rsa new file mode 100644 index 0000000..e037c08 --- /dev/null +++ b/ansible/vagrant/id_rsa @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAtTZwqqxn8VR0QgQCUMGyaql1Ht1GXSmcCT343b528k55jIr4 +cuaWwiZ+r3FebRh713TG7BVw+8JMiFsz41jW6j+VQTZzakoT3qQfu/IdTOkxbI6Z +5AmqOTOGv7iyV5DMpwsugSwsTCVCSiGIsTf/n5sMzUqjzlO6jVFG6leBEdq1Hds6 +ZuHlLxPUI4CwSeSrXcn03Usymxe8h1FoLLQVA2fsDrhcrPqXFa7byXqpCnQQhnL8 +VUx1cwmuglgRoBuIPvDh7eH/tj1J/U4Kwux22j8NwxxaEPnCsye212WdsMK5qJ6G +XHf6OwADpNHzQ0FF+r4D+rs6qIicPS7ULHFmrQIDAQABAoIBAQCels1VYNr6xkmU +eMO5/zpwxGr+nvJ0l/S51eWV0plwh6Myj3DNxeYMdfoK+rGD0piXP9jTRhSCEFJA +R2kKv3YevZSW5NtvGvN2trYbGtHvvGmHsukVPCwgMWrtIOvbXJruWgfR/mGqJjV0 +gRKK3hI1kVFL3NWsvXQXNxlT/06y2vcDaAfc+DUJyx0DvfZJmLpEOR5SlGn3c1mU +gg6k0XF4lGlGLXKtWwVKoMJNHFbiLxCXSo9gI+qja7M8vlR29yvjtKTPIkkBPWkd +MJTt2qvOFxGbRouVU1XbpvPOYd/u0sl05dBc6Kmkew0hJszAysNnXGqFsp8+z8Cu +q344ZiY1AoGBANkJGI5bLlK2EFzdd5h639kmyMkhjOdrJPlFW4EjIxn3Yv5TbQRi +u5AVie00o11eXrE9W3fSoHLymlkkpw3xoIWy5/JF2oTD2ea5h4jbfhhNoLthW9ub +Ggyt1UKrautxKAGuhZSzNz8J8rLtcRW4nt72InI1V990+Uj53f9LlEgDAoGBANW+ +7tYj63IBduCuvR7vLF4kwsUH/SLny6iSSl9JhJkJ8uESGa93VSiaUwRmNEhBXhmv +iAdduzRLUY4Tit1RK2/DYi4dN1UCgh8QuVyzC682pPlCTm+mv7CGv75H9R2XP+Cw +dWTSxYUu+A2icNTd0ANpW2Yy04gLJeIph5yZdw+PAoGAfWipHNEJMlfrmo2KJryR +jlu/16CgV7Rst/Dgz/zqsn1lYUn5i3g1oyse+Mbawv/dvZKTwOgfOGyAzZPFR+Rf ++gGHz1GX0/GLfquj6mvSL97jSoMWXg4AfmUP/qcocAWBtX8Pxv3LpYxtBgD3wDJe +8rzM6Kt0LDXeOdHP+k3Ez9sCgYBoD1ZzhnU/wZrAdBG6l7I/+yGfju4cKkEqRl5S +2ZXmc8N887TxieU5qTg1chSOANTxKFXPUECtiuWfh8AZU0UUWkjYLn0bs+bpfNjh +WoGbwby7ZR6OmN3F8TQ0TQ/2YgZFO2NLvJlQ57b33FeWKo70ujw3GxOErfi5jIJr +KQOf3QKBgQDSY6t/lfr5U1+GtuWZb0fhCamsqC9D90zzf80kkGKhPflGy7AXJc0z +vaJOP8Np1I8EmotgbXcp0PapkVNbp6U2uvtaSriMQjyFde6CU6+AH+aPipoQ9dO/ +Va42rZioyzqcn9azo+t6O3BbUn+0e1wHrOdsntKkC+mIdB0Xv5Ecig== +-----END RSA PRIVATE KEY----- diff --git a/ansible/vagrant/id_rsa.pub b/ansible/vagrant/id_rsa.pub new file mode 100644 index 0000000..cb6bd6c --- /dev/null +++ b/ansible/vagrant/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC1NnCqrGfxVHRCBAJQwbJqqXUe3UZdKZwJPfjdvnbyTnmMivhy5pbCJn6vcV5tGHvXdMbsFXD7wkyIWzPjWNbqP5VBNnNqShPepB+78h1M6TFsjpnkCao5M4a/uLJXkMynCy6BLCxMJUJKIYixN/+fmwzNSqPOU7qNUUbqV4ER2rUd2zpm4eUvE9QjgLBJ5KtdyfTdSzKbF7yHUWgstBUDZ+wOuFys+pcVrtvJeqkKdBCGcvxVTHVzCa6CWBGgG4g+8OHt4f+2PUn9TgrC7HbaPw3DHFoQ+cKzJ7bXZZ2wwrmonoZcd/o7AAOk0fNDQUX6vgP6uzqoiJw9LtQscWat varun@DESKTOP-HICNS5Q diff --git a/ansible/vars/dev.yml b/ansible/vars/dev.yml new file mode 100644 index 0000000..5126cbc --- /dev/null +++ b/ansible/vars/dev.yml @@ -0,0 +1,37 @@ +deployment_mysql_hospice_username: hospice_user +deployment_mysql_hospoce_password: dev@password +deployment_app_image: varunpalekar1/php-test:latest + +deployment_webserver: + ports: + - "80" + - "443" + volumes: + - ./:/var/www + - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ + +deployment_app: + image: "{{ deployment_app_image }}" + environment: + APP_ENV: dev + APP_DEBUG: "true" + APP_KEY: base64:oPD/hrRXGvA1hydZp17JAQH2PnflMgp4P5OMWoldWTM= + + DB_HOST: db + DB_DATABASE: laravel + DB_USERNAME: root + DB_PASSWORD: your_mysql_root_password + + JAEGER_HOST: jaeger + JAEGER_PORT: 6831 + JAEGER_ENABLE: "false" + volumes: + - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini + +deployment_db: + volumes: + - ./docker-data/mysql:/var/lib/mysql + - ./docker/mysql/my.cnf:/etc/mysql/my.cnf + environment: + MYSQL_DATABASE: laravel + MYSQL_ROOT_PASSWORD: your_mysql_root_password \ No newline at end of file diff --git a/ansible/vars/prod.yml b/ansible/vars/prod.yml new file mode 100644 index 0000000..b23ce20 --- /dev/null +++ b/ansible/vars/prod.yml @@ -0,0 +1,55 @@ +--- +mysql_root_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 61313835633639326662623933393862353361653161346634363638333366353765323631343866 + 6232366537616336333262663236643965653266643461320a643166336261363662393037303837 + 31313833326439616265393066373730383439613366626462643335633966633436353436633936 + 3361623431323365650a326163366662316431366364366230326137336630616233613166383364 + 3565 + +mysql_root_username: root + +deployment_mysql_hospice_name: hospice +deployment_mysql_hospice_username: hospice_user +deployment_mysql_hospoce_password: !vault | + $ANSIBLE_VAULT;1.1;AES256 + 33343136386364626234333131386135353238643462643939666137386235663131663834353561 + 3565623930363030636334633230396639303835643034390a306130373830303332653837613835 + 36346233396535643433383139366564643064343037373135333934376530623932653163303266 + 3466653231353838350a616466356430306463353239396361363737373339383664666663653963 + 3664 + +deployment_db: false +deployment_app_image: varunpalekar1/php-test:latest +deployment_webserver: + ports: + - "80" + - "443" + volumes: + - ./:/var/www + - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ + +deployment_app: + image: "{{ deployment_app_image }}" + environment: + APP_ENV: prod + APP_DEBUG: "true" + APP_KEY: base64:oPD/hrRXGvA1hydZp17JAQH2PnflMgp4P5OMWoldWTM= + + DB_HOST: localhost + DB_DATABASE: "{{ deployment_mysql_hospice_name }}" + DB_USERNAME: "{{ deployment_mysql_hospice_username }}" + DB_PASSWORD: "{{ deployment_mysql_hospoce_password }}" + + volumes: + - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini + +mysql_databases: + - name: "{{ deployment_mysql_hospice_name }}" + encoding: latin1 + collation: latin1_general_ci +mysql_users: + - name: "{{ deployment_mysql_hospice_username }}" + host: "%" + priv: "hospice.*:ALL" + password: "{{ deployment_mysql_hospoce_password }}" \ No newline at end of file diff --git a/app/Providers/OpenCensusProvider.php b/app/Providers/OpenCensusProvider.php new file mode 100644 index 0000000..4bd312c --- /dev/null +++ b/app/Providers/OpenCensusProvider.php @@ -0,0 +1,47 @@ + env('JAEGER_HOST', 'jaeger'), + "port" => env('JAEGER_PORT', '6831'), + "tags" => [], + 'client' => null + ]; + + // Start the request tracing for this request + $exporter = new JaegerExporter( env('APP_NAME', 'Laravel') ,$options); + + // $exporter = new EchoExporter(); + // $exporter = new FileExporter('/var/www/opentrace.log'); + Tracer::start($exporter); + + // Create a span that starts from when Laravel first boots (public/index.php) + Tracer::inSpan(['name' => 'bootstrap', 'startTime' => LARAVEL_START], function () {}); + } + + public function register() + { + // + } +} diff --git a/composer.json b/composer.json index e7bad62..5f68cef 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,9 @@ "laravel/framework": "5.2.*", "laravelcollective/html": "5.2.*", "mews/purifier": "^2.0", - "intervention/image": "^2.3" + "intervention/image": "^2.3", + "opencensus/opencensus": "^0.5.2", + "opencensus/opencensus-exporter-jaeger": "~0.1" }, "require-dev": { "fzaninotto/faker": "~1.4", diff --git a/composer.lock b/composer.lock index 7071d2e..1515cb5 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,168 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "5649cd1a53dabef16940992e0f03257a", + "content-hash": "1024a9bfa3991e98eb09239aba2c21f1", "packages": [ + { + "name": "apache/thrift", + "version": "0.11.0", + "source": { + "type": "git", + "url": "https://github.com/apache/thrift.git", + "reference": "327ebb6c2b6df8bf075da02ef45a2a034e9b79ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/apache/thrift/zipball/327ebb6c2b6df8bf075da02ef45a2a034e9b79ba", + "reference": "327ebb6c2b6df8bf075da02ef45a2a034e9b79ba", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": [] + }, + "autoload": { + "psr-0": { + "Thrift": "lib/php/lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Apache Thrift Developers", + "email": "dev@thrift.apache.org", + "homepage": "http://thrift.apache.org" + } + ], + "description": "Apache Thrift RPC system", + "homepage": "http://thrift.apache.org/", + "time": "2017-12-03T17:27:58+00:00" + }, + { + "name": "cache/adapter-common", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-cache/adapter-common.git", + "reference": "6320bb5f5574cb88438059b59f8708da6b6f1d32" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-cache/adapter-common/zipball/6320bb5f5574cb88438059b59f8708da6b6f1d32", + "reference": "6320bb5f5574cb88438059b59f8708da6b6f1d32", + "shasum": "" + }, + "require": { + "cache/tag-interop": "^1.0", + "php": "^5.6 || ^7.0", + "psr/cache": "^1.0", + "psr/log": "^1.0", + "psr/simple-cache": "^1.0" + }, + "require-dev": { + "cache/integration-tests": "^0.16", + "phpunit/phpunit": "^5.7.21" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Cache\\Adapter\\Common\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Aaron Scherer", + "email": "aequasi@gmail.com", + "homepage": "https://github.com/aequasi" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/nyholm" + } + ], + "description": "Common classes for PSR-6 adapters", + "homepage": "http://www.php-cache.com/en/latest/", + "keywords": [ + "cache", + "psr-6", + "tag" + ], + "time": "2018-07-08T13:04:33+00:00" + }, + { + "name": "cache/tag-interop", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-cache/tag-interop.git", + "reference": "c7496dd81530f538af27b4f2713cde97bc292832" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-cache/tag-interop/zipball/c7496dd81530f538af27b4f2713cde97bc292832", + "reference": "c7496dd81530f538af27b4f2713cde97bc292832", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "psr/cache": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "Cache\\TagInterop\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/nyholm" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com", + "homepage": "https://github.com/nicolas-grekas" + } + ], + "description": "Framework interoperable interfaces for tags", + "homepage": "http://www.php-cache.com/en/latest/", + "keywords": [ + "cache", + "psr", + "psr6", + "tag" + ], + "time": "2017-03-13T09:14:27+00:00" + }, { "name": "classpreloader/classpreloader", "version": "3.2.0", @@ -1110,6 +1267,110 @@ ], "time": "2016-09-16T12:04:44+00:00" }, + { + "name": "opencensus/opencensus", + "version": "v0.5.2", + "source": { + "type": "git", + "url": "https://github.com/census-instrumentation/opencensus-php.git", + "reference": "31dc521ba3fab9653a215a10e65d5b7fe9e2c6ac" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/census-instrumentation/opencensus-php/zipball/31dc521ba3fab9653a215a10e65d5b7fe9e2c6ac", + "reference": "31dc521ba3fab9653a215a10e65d5b7fe9e2c6ac", + "shasum": "" + }, + "require": { + "cache/adapter-common": "^1.0", + "php": ">=5.6", + "psr/cache": "^1.0", + "psr/log": "^1.0", + "ramsey/uuid": "~3" + }, + "conflict": { + "ext-opencensus": "< 0.1.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "~5.3", + "guzzlehttp/psr7": "~1.4", + "phpunit/phpunit": "^5.0", + "squizlabs/php_codesniffer": "2.*", + "symfony/yaml": "~3.3", + "twig/twig": "~2.0 || ~1.35" + }, + "suggest": { + "cache/apc-adapter": "Enable QpsSampler to use apc cache.", + "cache/apcu-adapter": "Enable QpsSampler to use apcu cache.", + "cache/memcached-adapter": "Enable QpsSampler to use memcached cache.", + "ext-opencensus": "Enable tracing arbitrary functions.", + "opencensus/opencensus-exporter-jaeger": "Export data to Jaeger", + "opencensus/opencensus-exporter-stackdriver": "Export data to Stackdriver", + "opencensus/opencensus-exporter-zipkin": "Export data to Zipkin" + }, + "type": "library", + "autoload": { + "psr-4": { + "OpenCensus\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jeff Ching", + "email": "chingor@google.com" + } + ], + "description": "OpenCensus Trace Client for PHP", + "time": "2018-09-25T20:57:09+00:00" + }, + { + "name": "opencensus/opencensus-exporter-jaeger", + "version": "v0.1.1", + "source": { + "type": "git", + "url": "https://github.com/census-ecosystem/opencensus-php-exporter-jaeger.git", + "reference": "29480c3e77a4e7a1359cd9e66e32da7446d18bb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/census-ecosystem/opencensus-php-exporter-jaeger/zipball/29480c3e77a4e7a1359cd9e66e32da7446d18bb6", + "reference": "29480c3e77a4e7a1359cd9e66e32da7446d18bb6", + "shasum": "" + }, + "require": { + "apache/thrift": "^0.11", + "ext-sockets": "*", + "opencensus/opencensus": "~0.4", + "php-64bit": ">=5.6" + }, + "require-dev": { + "guzzlehttp/guzzle": "~6.0", + "phpunit/phpunit": "^5.0", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "OpenCensus\\Trace\\Exporter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Jeff Ching", + "email": "chingor@google.com" + } + ], + "description": "OpenCensus Jaeger Exporter for PHP", + "time": "2018-11-26T18:31:31+00:00" + }, { "name": "paragonie/random_compat", "version": "v1.4.3", @@ -1158,6 +1419,52 @@ ], "time": "2018-04-04T21:48:54+00:00" }, + { + "name": "psr/cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", + "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "time": "2016-08-06T20:24:11+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -1255,6 +1562,54 @@ ], "time": "2018-11-20T15:27:04+00:00" }, + { + "name": "psr/simple-cache", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "time": "2017-10-23T01:57:42+00:00" + }, { "name": "psy/psysh", "version": "v0.7.2", @@ -1367,6 +1722,88 @@ "description": "A polyfill for getallheaders.", "time": "2016-02-11T07:05:27+00:00" }, + { + "name": "ramsey/uuid", + "version": "3.8.0", + "source": { + "type": "git", + "url": "https://github.com/ramsey/uuid.git", + "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/d09ea80159c1929d75b3f9c60504d613aeb4a1e3", + "reference": "d09ea80159c1929d75b3f9c60504d613aeb4a1e3", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "^1.0|^2.0|9.99.99", + "php": "^5.4 || ^7.0", + "symfony/polyfill-ctype": "^1.8" + }, + "replace": { + "rhumsaa/uuid": "self.version" + }, + "require-dev": { + "codeception/aspect-mock": "^1.0 | ~2.0.0", + "doctrine/annotations": "~1.2.0", + "goaop/framework": "1.0.0-alpha.2 | ^1.0 | ~2.1.0", + "ircmaxell/random-lib": "^1.1", + "jakub-onderka/php-parallel-lint": "^0.9.0", + "mockery/mockery": "^0.9.9", + "moontoast/math": "^1.1", + "php-mock/php-mock-phpunit": "^0.3|^1.1", + "phpunit/phpunit": "^4.7|^5.0|^6.5", + "squizlabs/php_codesniffer": "^2.3" + }, + "suggest": { + "ext-ctype": "Provides support for PHP Ctype functions", + "ext-libsodium": "Provides the PECL libsodium extension for use with the SodiumRandomGenerator", + "ext-uuid": "Provides the PECL UUID extension for use with the PeclUuidTimeGenerator and PeclUuidRandomGenerator", + "ircmaxell/random-lib": "Provides RandomLib for use with the RandomLibAdapter", + "moontoast/math": "Provides support for converting UUID to 128-bit integer (in string form).", + "ramsey/uuid-console": "A console application for generating UUIDs with ramsey/uuid", + "ramsey/uuid-doctrine": "Allows the use of Ramsey\\Uuid\\Uuid as Doctrine field type." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Ramsey\\Uuid\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marijn Huizendveld", + "email": "marijn.huizendveld@gmail.com" + }, + { + "name": "Thibaud Fabre", + "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" + } + ], + "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", + "homepage": "https://github.com/ramsey/uuid", + "keywords": [ + "guid", + "identifier", + "uuid" + ], + "time": "2018-07-19T23:38:55+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v5.4.12", diff --git a/config/app.php b/config/app.php index ed465fe..d56cbd6 100644 --- a/config/app.php +++ b/config/app.php @@ -160,6 +160,9 @@ Intervention\Image\ImageServiceProvider::class, + // Opencensus + App\Providers\OpenCensusProvider::class, + ], /* diff --git a/docker-compose.local.yml b/docker-compose.local.yml new file mode 100644 index 0000000..91aa50b --- /dev/null +++ b/docker-compose.local.yml @@ -0,0 +1,90 @@ +version: "3" + +services: + # Nginx web server + webserver: + image: nginx:alpine + container_name: webserver + restart: unless-stopped + tty: true + ports: + - "80:80" + - "443:443" + volumes: + - ./:/var/www + - ./docker/nginx/conf.d/:/etc/nginx/conf.d/ + networks: + - app-network + + # PHP-fpm server + app: + build: + context: . + dockerfile: Dockerfile + image: varun/laravel-php-fpm + container_name: app + restart: unless-stopped + tty: true + environment: + SERVICE_NAME: app + SERVICE_TAGS: dev + TERM: xterm + APP_ENV: local + XDEBUG_CONFIG: idekey=PHPSTORM + working_dir: /var/www + volumes: + - ./:/var/www + - ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini + networks: + - app-network + + ## MYSQL db + db: + image: mysql:5.7.22 + container_name: db + restart: unless-stopped + tty: true + # ports: + # - "3306:3306" + volumes: + - ./docker-data/mysql:/var/lib/mysql + - ./docker/mysql/my.cnf:/etc/mysql/my.cnf + environment: + MYSQL_DATABASE: laravel + MYSQL_ROOT_PASSWORD: your_mysql_root_password + SERVICE_TAGS: dev + SERVICE_NAME: mysql + networks: + - app-network + + phpmyadmin: + image: phpmyadmin/phpmyadmin + restart: always + environment: + PMA_HOST: db + ports: + - 8001:80 + networks: + - app-network + + # # You can enable this if don't want to host jaeger outside + jaeger: + # container_name: laravel_jaeger + image: jaegertracing/all-in-one:1.6 + restart: always + ports: + # - 5775:5775/udp + - 6831:6831/udp + - 6832:6832/udp + # - 5778:5778 + - 16686:16686 + # - 14268:14268 + # - 9411:9411 + environment: + COLLECTOR_ZIPKIN_HTTP_PORT: 9411 + networks: + - app-network + +networks: + app-network: + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3de37dc --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,28 @@ +version: "3" + +services: + # Nginx web server + webserver: + image: nginx:alpine + container_name: webserver + restart: unless-stopped + tty: true + networks: + - app-network + + # PHP-fpm server + app: + build: + context: . + dockerfile: Dockerfile + image: varun/laravel-php-fpm + container_name: app + restart: unless-stopped + tty: true + working_dir: /var/www + networks: + - app-network + +networks: + app-network: + driver: bridge diff --git a/docker-local.sh b/docker-local.sh new file mode 100644 index 0000000..822e41d --- /dev/null +++ b/docker-local.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +docker-compose -f docker-compose.yml -f docker-compose.local.yml $@ \ No newline at end of file diff --git a/docker/mysql/my.cnf b/docker/mysql/my.cnf new file mode 100644 index 0000000..1c50b02 --- /dev/null +++ b/docker/mysql/my.cnf @@ -0,0 +1,3 @@ +[mysqld] +general_log = 1 +general_log_file = /var/lib/mysql/general.log diff --git a/docker/nginx/conf.d/laravel.conf b/docker/nginx/conf.d/laravel.conf new file mode 100644 index 0000000..4c6cbf4 --- /dev/null +++ b/docker/nginx/conf.d/laravel.conf @@ -0,0 +1,20 @@ +server { + listen 80; + index index.php index.html; + error_log /var/log/nginx/error.log; + access_log /var/log/nginx/access.log; + root /var/www/public; + location ~ \.php$ { + try_files $uri =404; + fastcgi_split_path_info ^(.+\.php)(/.+)$; + fastcgi_pass app:9000; + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + } + location / { + try_files $uri $uri/ /index.php?$query_string; + gzip_static on; + } +} \ No newline at end of file diff --git a/docker/opencensus/agent.yml b/docker/opencensus/agent.yml new file mode 100644 index 0000000..57f8f56 --- /dev/null +++ b/docker/opencensus/agent.yml @@ -0,0 +1,4 @@ +receivers: + jaeger: + collector_thrift_port: 14267 + collector_http_port: 14268 \ No newline at end of file diff --git a/docker/opencensus/collector.yml b/docker/opencensus/collector.yml new file mode 100644 index 0000000..e69de29 diff --git a/docker/php/local.ini b/docker/php/local.ini new file mode 100644 index 0000000..879b067 --- /dev/null +++ b/docker/php/local.ini @@ -0,0 +1,4 @@ +upload_max_filesize=40M +post_max_size=40M +extension=opencensus.so +log_errors=on \ No newline at end of file diff --git a/docker/prometheus/prometheus.yml b/docker/prometheus/prometheus.yml new file mode 100644 index 0000000..5048f7a --- /dev/null +++ b/docker/prometheus/prometheus.yml @@ -0,0 +1,19 @@ +scrape_configs: + # Scrape Prometheus itself every 5 seconds. + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: + - localhost:9090 + + # Scrape the Node Exporter every 5 seconds. + - job_name: 'jaeger' + scrape_interval: 5s + static_configs: + - targets: + - jaeger:16686 + - job_name: nginx + scrape_interval: 5s + static_configs: + - targets: + - nginx_exporter:9113 \ No newline at end of file diff --git a/public/- Copy.htaccess b/public/- Copy.htaccess deleted file mode 100644 index 8eb2dd0..0000000 --- a/public/- Copy.htaccess +++ /dev/null @@ -1,16 +0,0 @@ - - - Options -MultiViews - - - RewriteEngine On - - # Redirect Trailing Slashes If Not A Folder... - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule ^(.*)/$ /$1 [L,R=301] - - # Handle Front Controller... - RewriteCond %{REQUEST_FILENAME} !-d - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] - diff --git a/read.txt b/read.txt deleted file mode 100644 index 0084e7e..0000000 --- a/read.txt +++ /dev/null @@ -1,13 +0,0 @@ -1)Open your .env file and change the database name (DB_DATABASE) -2)To Migrate DB use following command - >> Run php artisan migrate - -3)To Run DB Seeding(dummy data); - - >> php artisan db:seed --class=UsersTableSeeder - >> php artisan db:seed --class=PostsTableSeeder - >> php artisan db:seed --class=PostsTableSeeder - - 4)To Run Test Cases - - >> Run phpunit \ No newline at end of file diff --git a/readme.md b/readme.md index b1043b7..19aaf6f 100644 --- a/readme.md +++ b/readme.md @@ -1,15 +1,142 @@ -# How To Build a (Basic) Blog with Laravel - -1)Open your .env file and change the database name (DB_DATABASE) -2)To Migrate DB use following command - >> Run php artisan migrate - -3)To Run DB Seeding(dummy data); - - >> php artisan db:seed --class=UsersTableSeeder - >> php artisan db:seed --class=PostsTableSeeder - >> php artisan db:seed --class=PostsTableSeeder - - 4)To Run Test Cases - - >> Run phpunit \ No newline at end of file +Introduction +=========== + +This repository shows complete CI/CD of sample PHP project. We are going to use following tools/technologies: + +1. Jenkins: For integration various tools and technologies +2. PHP project in Laravel: We are having one blog project by using PHP laravel framework +3. Ansible: For deployment on dev and prod +4. Docker with docker-compose: For using deployment on local, dev and prod env +5. Sonarqube: Using sonarqube.io server of static code analysis and code coverage report +6. Branching: Following git-flow branching strategy +7. Using opencensus for distributed tracing + +Folder structure +================ + +``` +├── ansible => ansible folder +│   ├── hosts-dev => ansible hosts file for dev +│   ├── hosts-prod => ansible hosts file for prod +│   ├── playbook.yml => ansible playbook +│   ├── requirements.yml => ansible-galaxy requirement file for other role +│   ├── roles => ansible role folder +│   │   └── deployment => ansible main role for deployment +│   ├── vagrant => vagrant file need to share if you are using vagrant +│   ├── Vagrantfile => vagrantfile for creating dev and prod env if you want to create in an automated way +│   └── vars => ansible folder having some extra variable +│   ├── dev.yml => ansible variable file for dev env +│   └── prod.yml => ansible variable file for prod env +├── app => Laravel app folder +├── artisan => Laravel artisan file +├── bootstrap => Laravel bootstrap folder +├── composer.json => PHP composer file +├── composer.lock => PHP composer lock file +├── config => Laravel config folder +├── database => Laravel database folder +│   ├── factories => Laravel factories folder which used for seeding +│   │   └── ModelFactory.php +│   ├── migrations => Laravel migration folder used for database migration +│   │   ├── 2014_10_12_000000_create_users_table.php +│   │   ├── 2014_10_12_100000_create_password_resets_table.php +│   │   ├── 2016_02_06_175142_create_posts_table.php +│   │   ├── 2016_03_20_162017_add_slug_to_users.php +│   │   ├── 2016_04_28_021908_create_categories_table.php +│   │   ├── 2016_04_28_022255_add_category_id_to_posts.php +│   │   ├── 2016_05_30_153615_create_tags_table.php +│   │   ├── 2016_05_30_155417_create_post_tag_table.php +│   │   ├── 2016_07_16_173641_create_comments_table.php +│   │   ├── 2016_08_15_000718_add_image_col_to_posts.php +│   │   └── 2019_06_28_133124_create_books_table.php +│   └── seeds => Laravel seeds folder used for database seeding +│   ├── BookTableSeeder.php +│   ├── CategoryTableSeeder.php +│   ├── DatabaseSeeder.php +│   ├── PostsTableSeeder.php +│   └── UsersTableSeeder.php +├── docker => Folder contains some configuration file used by docker container +│   ├── mysql +│   │   └── my.cnf => default configuration file for mysql used in local and dev env only, in prodution we prefer to use standalone managed mysql database +│   ├── nginx +│   │   └── conf.d +│   │   └── laravel.conf => Nginx configuration used for docker container (all env) +│   ├── php +│   │   └── local.ini => Php configuration used for docker container (all env) +├── docker-compose.local.yml => Docker-compose override file for local deployment using docker +├── docker-compose.yml => Default docker-compose file shared by all env +├── Dockerfile => Dockerfile used to build default php application docker container +├── gulpfile.js => Laravel gulpfile +├── Jenkinsfile => Jenkinsfile in which all CI/CD defined for this project +├── package.json => Default composer package.json +├── phpunit.xml +├── public => Laravel public folder +├── resources => Laravel resources folder +├── server.php => Laravel server file +├── sonar-project.properties => sonar-scanner properties file related to project +├── storage => Laravel storage folder +└── tests => Php unit test folder +``` + +Jenkins +======= + +You can directly use jenkinsfile for all CI/CD. I am suggesting to use jenkins ocean blue to add pipeline by git project simply. Just go to new pipeline and add by using git URL. + +Deployment +========== + +### Local deployment + +1. Requirement: + 1. docker + 2. docker-compose + 3. php-cli with composer + +2. Deployment + + Run following command to deploy the project on local system by using docker-compose + + ``` + docker-compose -f docker-compose.yml -f docker-compose.local.yml up -d + ``` + +3. Install project dependencies + + ``` + composer install + ``` + +4. Run migration + + ``` + docker-compose -f docker-compose.yml -f docker-compose.local.yml exec app php artisan migrate + ``` + +5. Run seeding + + ``` + docker-compose -f docker-compose.yml -f docker-compose.local.yml exec app php db:seed --class=UsersTableSeeder + docker-compose -f docker-compose.yml -f docker-compose.local.yml exec app php db:seed --class=PostsTableSeeder + docker-compose -f docker-compose.yml -f docker-compose.local.yml exec app php db:seed --class=PostsTableSeeder + + ``` + +6. Application access + + Now you can access your application by using URL `http://localhost/` + +7. Distributed tracing in Jaeger UI + + You can access Jaeger UI to see distributed tracing of you running application `http://localhost:16686` + +### Dev deployment + +Please use jenkins-pipeline for deployment on dev. + +We are using ansible for deployment on dev. Please change `ansible/hosts-dev` for changing deployment node for dev. By default it run ansible playbook on all hosts. + +### Prod deployment + +Please use jenkins-pipeline for deployment on prod + +We are using ansible for deployment on dev. Please change `ansible/hosts-prod` for changing deployment node for dev. By default it run ansible playbook on all hosts. diff --git a/sonar-project.properties b/sonar-project.properties new file mode 100644 index 0000000..c90d27b --- /dev/null +++ b/sonar-project.properties @@ -0,0 +1,25 @@ +# Required metadata +sonar.projectKey=php-test +sonar.projectName=php-test +sonar.projectVersion=1.0.0 + +# Path to the parent source code directory. +sonar.sources=app + +# Language +# We've commented this out, because we want to analyse both PHP and Javascript +#sonar.language=php + +# Encoding of the source code +sonar.sourceEncoding=UTF-8 + +# Reusing PHPUnit reports +sonar.php.coverage.reportPath=reports/codeCoverage.xml +sonar.php.tests.reportPath=reports/junit.xml + +# Here, you can exclude all the directories that you don't want to analyse. +# As an example, I'm excluding the Providers directory +sonar.exclusions=app/Providers/** + +# Additional parameters +#sonar.my.property=value \ No newline at end of file diff --git a/storage/app/.gitignore b/storage/app/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/storage/app/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/storage/framework/.gitignore b/storage/framework/.gitignore new file mode 100644 index 0000000..953edb7 --- /dev/null +++ b/storage/framework/.gitignore @@ -0,0 +1,7 @@ +config.php +routes.php +compiled.php +services.json +events.scanned.php +routes.scanned.php +down diff --git a/storage/framework/cache/.gitignore b/storage/framework/cache/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/storage/framework/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/storage/framework/sessions/.gitignore b/storage/framework/sessions/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/sessions/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/framework/views/.gitignore b/storage/framework/views/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/framework/views/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/storage/logs/.gitignore b/storage/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/storage/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore