diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..7c965e5 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,21 @@ +name: Docker +on: + push: + # Publish `master` as Docker `latest` image. + branches: + - master + +jobs: + # Run tests. + # See also https://docs.docker.com/docker-hub/builds/automated-testing/ + test: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Run tests + run: | + docker build . --file dockerfile -t mahmom/jenkins_iti:v1.10 + docker login -u ${{ secrets.DOCKER_USERNAME}} -p ${{secrets.DOCKER_PASSWORD}} + docker push mahmom/jenkins_iti:v1.10 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..1cec31f --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,61 @@ +name: nodejs-workflow + +on: + pull_request: + branches: + - master + push: + branches: + - master + +jobs: + + testing: + runs-on: self-hosted + steps: + - name: checkout repo + uses: actions/checkout@v4 + + - name: SonarQube scan + uses: SonarSource/sonarqube-scan-action@v2 + env: + SONAR_HOST_URL: http://localhost:9001 + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + with: + args: > + -Dsonar.projectKey=nodejs-workflow + -Dsonar.sources=. + + - name: Quality Gate + uses: SonarSource/sonarqube-quality-gate-action@v1 + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + build: + needs: testing + runs-on: self-hosted + steps: + - name: checkout repo + uses: actions/checkout@v4 + + - name: docker login + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: build image + run: | + docker build -t danamostafa/nodejs:latest . + docker push danamostafa/nodejs:latest + + deployment: + needs: build + if: github.ref == 'refs/heads/master' + runs-on: self-hosted + steps: + - name: checkout repo + uses: actions/checkout@v4 + + - name: apply k8s manifest file + run: kubectl apply -f k8s/ \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..276a7ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.scannerwork/ +node_modules/ +package-lock.json + \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile deleted file mode 100644 index 6aaab56..0000000 --- a/Jenkinsfile +++ /dev/null @@ -1,25 +0,0 @@ - -pipeline { - agent any - stages { - stage('Build') { - steps { - sh 'docker build -f dockerfile . -t mahmom/jenkins_node:v1.0' - } - } - stage('push') { - steps { - withCredentials([usernamePassword(credentialsId:"docker",usernameVariable:"USERNAME",passwordVariable:"PASSWORD")]){ - sh 'docker login --username $USERNAME --password $PASSWORD' - sh 'docker push mahmom/jenkins_node:v1.0' - } - - } - } - stage('Deploy') { - steps { - sh 'docker run -d -p 3000:3000 mahmom/jenkins_node:v1.0' - } - } - } -} diff --git a/dockerfile b/dockerfile index 08efcf2..4faf207 100644 --- a/dockerfile +++ b/dockerfile @@ -1,5 +1,10 @@ -FROM node:12 -COPY nodeapp /nodeapp +FROM node:18 + WORKDIR /nodeapp + +COPY nodeapp/package*.json ./ RUN npm install -CMD ["node", "/nodeapp/app.js"] \ No newline at end of file + +COPY nodeapp . + +CMD ["node", "app.js"] \ No newline at end of file diff --git a/k8s/config.yml b/k8s/config.yml new file mode 100644 index 0000000..2779ced --- /dev/null +++ b/k8s/config.yml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: mysql-config + namespace: nodejs +data: + DB_HOST: mysql + DB_USER: root + DB_NAME: mydb + DB_PORT: "3306" \ No newline at end of file diff --git a/k8s/deployment.yml b/k8s/deployment.yml new file mode 100644 index 0000000..54456b4 --- /dev/null +++ b/k8s/deployment.yml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nodejs-deployment + namespace: nodejs + labels: + app: backend + +spec: + replicas: 2 + + selector: + matchLabels: + app: backend + + template: + metadata: + labels: + app: backend + + spec: + containers: + - name: nodejs + image: danamostafa/nodejs:latest + + ports: + - containerPort: 3000 + + env: + - name: DB_HOST + valueFrom: + configMapKeyRef: + name: mysql-config + key: DB_HOST + + - name: DB_USER + valueFrom: + configMapKeyRef: + name: mysql-config + key: DB_USER + + - name: DB_NAME + valueFrom: + configMapKeyRef: + name: mysql-config + key: DB_NAME + + - name: DB_PORT + valueFrom: + configMapKeyRef: + name: mysql-config + key: DB_PORT + + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: mysql-secret + key: MYSQL_ROOT_PASSWORD + + resources: + requests: + cpu: "100m" + memory: "128Mi" + limits: + cpu: "250m" + memory: "256Mi" + + readinessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 5 + + livenessProbe: + httpGet: + path: / + port: 3000 + initialDelaySeconds: 10 \ No newline at end of file diff --git a/k8s/mysqlsev.yml b/k8s/mysqlsev.yml new file mode 100644 index 0000000..e998252 --- /dev/null +++ b/k8s/mysqlsev.yml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql + namespace: nodejs +spec: + clusterIP: None + selector: + app: mysql + ports: + - port: 3306 + targetPort: 3306 \ No newline at end of file diff --git a/k8s/nodejsev.yml b/k8s/nodejsev.yml new file mode 100644 index 0000000..2703d4b --- /dev/null +++ b/k8s/nodejsev.yml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + name: nodejs + namespace: nodejs +spec: + type: NodePort + selector: + app: backend + ports: + - port: 3000 + targetPort: 3000 + nodePort: 30828 + \ No newline at end of file diff --git a/k8s/ns.yml b/k8s/ns.yml new file mode 100644 index 0000000..3658569 --- /dev/null +++ b/k8s/ns.yml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: nodejs + labels: + name: development diff --git a/k8s/pv.yml b/k8s/pv.yml new file mode 100644 index 0000000..21da9a5 --- /dev/null +++ b/k8s/pv.yml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: mysql-pv +spec: + capacity: + storage: 1Gi + + accessModes: + - ReadWriteOnce + + hostPath: + path: /data/mysql \ No newline at end of file diff --git a/k8s/pvc.yml b/k8s/pvc.yml new file mode 100644 index 0000000..d2922ff --- /dev/null +++ b/k8s/pvc.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pvc + namespace: nodejs + +spec: + volumeName: mysql-pv + + storageClassName: "" + + accessModes: + - ReadWriteOnce + + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/k8s/secret.yml b/k8s/secret.yml new file mode 100644 index 0000000..e0a7519 --- /dev/null +++ b/k8s/secret.yml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: mysql-secret + namespace: nodejs +data: + MYSQL_ROOT_PASSWORD: bXlwYXNzd29yZA== \ No newline at end of file diff --git a/k8s/statefulset.yml b/k8s/statefulset.yml new file mode 100644 index 0000000..1a5c5ff --- /dev/null +++ b/k8s/statefulset.yml @@ -0,0 +1,48 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: mysql + namespace: nodejs + +spec: + serviceName: mysql + replicas: 1 + + selector: + matchLabels: + app: mysql + + template: + metadata: + labels: + app: mysql + + spec: + containers: + - name: mysql + image: mysql:8.0 + + ports: + - containerPort: 3306 + + env: + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: mysql-secret + key: MYSQL_ROOT_PASSWORD + + - name: MYSQL_DATABASE + valueFrom: + configMapKeyRef: + name: mysql-config + key: DB_NAME + + volumeMounts: + - name: mysql-storage + mountPath: /var/lib/mysql + + volumes: + - name: mysql-storage + persistentVolumeClaim: + claimName: mysql-pvc \ No newline at end of file diff --git a/nodeapp/app.js b/nodeapp/app.js index 893a8fe..cb4c0d3 100644 --- a/nodeapp/app.js +++ b/nodeapp/app.js @@ -1,10 +1,29 @@ +const mysql = require('mysql2'); const express = require('express') const app = express() const port = 3000 +const host= process.env.DB_HOST +const user= process.env.DB_USER +const password= process.env.DB_PASSWORD +const database= process.env.DB_NAME; + +const connection = mysql.createConnection({ + host: host, + user: user, + password: password, + database: database +}); +connection.connect((err) => { + if (err) throw err; + console.log('Connected!'); +}); + app.get('/', (req, res) => { res.send('Hello World!') }) app.listen(port, () => { console.log(`Example app listening at http://localhost:${port}`) - }) \ No newline at end of file + }) + + \ No newline at end of file diff --git a/nodeapp/package.json b/nodeapp/package.json index 85a6cee..8ca60e7 100644 --- a/nodeapp/package.json +++ b/nodeapp/package.json @@ -10,5 +10,8 @@ "author": "", "license": "ISC", "dependencies": { - "express": "^4.17.1" } + "express": "^4.17.1", + "mysql": "^2.18.1", + "mysql2": "^3.22.3" + } }