diff --git a/assignment-4/Dockerfile b/assignment-4/Dockerfile new file mode 100644 index 0000000..b7b21be --- /dev/null +++ b/assignment-4/Dockerfile @@ -0,0 +1,6 @@ +FROM golang:1.18-alpine +RUN mkdir /backend-app +COPY . /backend-app +WORKDIR /backend-app +RUN go build -o main . +CMD ["/backend-app/main"] \ No newline at end of file diff --git a/assignment-4/backend-app/backend-deployment.yaml b/assignment-4/backend-app/backend-deployment.yaml new file mode 100644 index 0000000..8bc409a --- /dev/null +++ b/assignment-4/backend-app/backend-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend-app-deployment + labels: + app: backend-app +spec: + replicas: 3 + selector: + matchLabels: + app: backend-app + template: + metadata: + labels: + app: backend-app + spec: + containers: + - name: backend-app + image: pratikpjain/app + env: + - name: SVC_HOST_NAME + value: "backend-app" + - name: SVC_HOST_PORT + value: "8080" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/assignment-4/backend-app/backend-svc.yaml b/assignment-4/backend-app/backend-svc.yaml new file mode 100644 index 0000000..ae9e331 --- /dev/null +++ b/assignment-4/backend-app/backend-svc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: backendapp-service +spec: + selector: + app.kubernetes.io/name: backend-app + ports: + - protocol: TCP + port: 80 + targetPort: 9376 \ No newline at end of file diff --git a/assignment-4/backend-app/postgres-deployment.yaml b/assignment-4/backend-app/postgres-deployment.yaml new file mode 100644 index 0000000..7a117a3 --- /dev/null +++ b/assignment-4/backend-app/postgres-deployment.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + selector: + matchLabels: + app: postgres + strategy: + type: Recreate + template: + metadata: + labels: + app: postgres + spec: + containers: + - image: postgres:alpine + name: postgres + env: + - name: POSTGRES_DB + value: store + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: root + ports: + - containerPort: 5433 \ No newline at end of file diff --git a/assignment-4/backend-app/postgres-svc.yaml b/assignment-4/backend-app/postgres-svc.yaml new file mode 100644 index 0000000..bce32d0 --- /dev/null +++ b/assignment-4/backend-app/postgres-svc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + ports: + - port: 5432 + selector: + app: postgres + clusterIP: None \ No newline at end of file diff --git a/assignment-4/db/db.go b/assignment-4/db/db.go new file mode 100644 index 0000000..b056ced --- /dev/null +++ b/assignment-4/db/db.go @@ -0,0 +1,54 @@ +package db + +import ( + "database/sql" + "time" + + _ "github.com/jackc/pgconn" + _ "github.com/jackc/pgx/v4" + _ "github.com/jackc/pgx/v4/stdlib" +) + +type DB struct { + SQL *sql.DB +} + +var dbConn = &DB{} + +const maxOpenDbConn = 64 +const maxIdleDbConn = 64 +const maxDbLifeTime = 5 * time.Minute + +func ConnectDB(desc string) (*DB, error) { + + db, err := NewDatabase(desc) + + if err != nil { + panic(err) + } + + db.SetMaxOpenConns(maxOpenDbConn) + db.SetMaxIdleConns(maxIdleDbConn) + db.SetConnMaxLifetime(maxDbLifeTime) + + dbConn.SQL = db + + return dbConn, nil +} + +func NewDatabase(desc string) (*sql.DB, error) { + db, err := sql.Open("pgx", desc) + if err != nil { + return nil, err + } + + if err = db.Ping(); err != nil { + return nil, err + } + + return db, nil +} + +func GetDB() *sql.DB { + return dbConn.SQL +} diff --git a/assignment-4/docker-compose.yml b/assignment-4/docker-compose.yml new file mode 100644 index 0000000..f58eb87 --- /dev/null +++ b/assignment-4/docker-compose.yml @@ -0,0 +1,32 @@ +version: "3.8" + +services: + db: + image: postgres:alpine + container_name: "postgres" + ports: + - "5433:5433" + environment: + - POSTGRES_DB=store + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=root + networks: + - fullstack + volumes: + - database_postgres:/var/lib/postgresql/data + + web: + build: . + container_name: "backend-app" + command: ["go", "run", "main.go"] + ports: + - "8080:8080" + depends_on: + - db + networks: + - fullstack +volumes: + database_postgres: +networks: + fullstack: + driver: bridge \ No newline at end of file diff --git a/assignment-4/go.mod b/assignment-4/go.mod new file mode 100644 index 0000000..6463d9e --- /dev/null +++ b/assignment-4/go.mod @@ -0,0 +1,17 @@ +module github.com/practice + +go 1.18 + +require ( + github.com/gorilla/mux v1.8.0 // indirect + github.com/jackc/chunkreader/v2 v2.0.1 // indirect + github.com/jackc/pgconn v1.14.0 // indirect + github.com/jackc/pgio v1.0.0 // indirect + github.com/jackc/pgpassfile v1.0.0 // indirect + github.com/jackc/pgproto3/v2 v2.3.2 // indirect + github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgtype v1.14.0 // indirect + github.com/jackc/pgx/v4 v4.18.1 // indirect + golang.org/x/crypto v0.6.0 // indirect + golang.org/x/text v0.7.0 // indirect +) diff --git a/assignment-4/go.sum b/assignment-4/go.sum new file mode 100644 index 0000000..35432f3 --- /dev/null +++ b/assignment-4/go.sum @@ -0,0 +1,192 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q= +github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.3.2 h1:7eY55bdBeCz1F2fTzSz69QC+pG46jYq9/jtSPiJ5nn0= +github.com/jackc/pgproto3/v2 v2.3.2/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= +github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= +github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= +github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/assignment-4/helm-chart/.helmignore b/assignment-4/helm-chart/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/assignment-4/helm-chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/assignment-4/helm-chart/Chart.yaml b/assignment-4/helm-chart/Chart.yaml new file mode 100644 index 0000000..2e75792 --- /dev/null +++ b/assignment-4/helm-chart/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: backend-app +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/assignment-4/helm-chart/templates/backend-service-template/backend-deployment.yaml b/assignment-4/helm-chart/templates/backend-service-template/backend-deployment.yaml new file mode 100644 index 0000000..8bc409a --- /dev/null +++ b/assignment-4/helm-chart/templates/backend-service-template/backend-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: backend-app-deployment + labels: + app: backend-app +spec: + replicas: 3 + selector: + matchLabels: + app: backend-app + template: + metadata: + labels: + app: backend-app + spec: + containers: + - name: backend-app + image: pratikpjain/app + env: + - name: SVC_HOST_NAME + value: "backend-app" + - name: SVC_HOST_PORT + value: "8080" + ports: + - containerPort: 80 \ No newline at end of file diff --git a/assignment-4/helm-chart/templates/backend-service-template/backend-svc.yaml b/assignment-4/helm-chart/templates/backend-service-template/backend-svc.yaml new file mode 100644 index 0000000..ae9e331 --- /dev/null +++ b/assignment-4/helm-chart/templates/backend-service-template/backend-svc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: backendapp-service +spec: + selector: + app.kubernetes.io/name: backend-app + ports: + - protocol: TCP + port: 80 + targetPort: 9376 \ No newline at end of file diff --git a/assignment-4/helm-chart/templates/ingress.yaml b/assignment-4/helm-chart/templates/ingress.yaml new file mode 100644 index 0000000..03a1cf5 --- /dev/null +++ b/assignment-4/helm-chart/templates/ingress.yaml @@ -0,0 +1,10 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: ingress-backendapp +spec: + defaultBackend: + service: + name: backendapp-service + port: + number: 8080 diff --git a/assignment-4/helm-chart/templates/postgres-service-template/postgres-deployment.yaml b/assignment-4/helm-chart/templates/postgres-service-template/postgres-deployment.yaml new file mode 100644 index 0000000..7a117a3 --- /dev/null +++ b/assignment-4/helm-chart/templates/postgres-service-template/postgres-deployment.yaml @@ -0,0 +1,27 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres +spec: + selector: + matchLabels: + app: postgres + strategy: + type: Recreate + template: + metadata: + labels: + app: postgres + spec: + containers: + - image: postgres:alpine + name: postgres + env: + - name: POSTGRES_DB + value: store + - name: POSTGRES_USER + value: postgres + - name: POSTGRES_PASSWORD + value: root + ports: + - containerPort: 5433 \ No newline at end of file diff --git a/assignment-4/helm-chart/templates/postgres-service-template/postgres-svc.yaml b/assignment-4/helm-chart/templates/postgres-service-template/postgres-svc.yaml new file mode 100644 index 0000000..bce32d0 --- /dev/null +++ b/assignment-4/helm-chart/templates/postgres-service-template/postgres-svc.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Service +metadata: + name: postgres +spec: + ports: + - port: 5432 + selector: + app: postgres + clusterIP: None \ No newline at end of file diff --git a/assignment-4/helm-chart/values.yaml b/assignment-4/helm-chart/values.yaml new file mode 100644 index 0000000..fa12666 --- /dev/null +++ b/assignment-4/helm-chart/values.yaml @@ -0,0 +1,7 @@ +# Default values for helm-chart. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +backend-app: + image: pratikjain/app + servicePort: 80 \ No newline at end of file diff --git a/assignment-4/main.go b/assignment-4/main.go new file mode 100644 index 0000000..e3401b5 --- /dev/null +++ b/assignment-4/main.go @@ -0,0 +1,55 @@ +package main + +import ( + "encoding/json" + "fmt" + "net/http" + + "github.com/gorilla/mux" + "github.com/practice/db" + "github.com/practice/service/user_service" +) + +// const ( +// host = "localhost" +// port = 5432 +// user = "postgres" +// password = "root" +// dbname = "store" +// ) + +func main() { + connectToDB() + handlers() +} + +func connectToDB() { + dbDesc := "postgres://postgres:root@db:5433/store?sslmode=disable" + db.ConnectDB(dbDesc) + fmt.Println("Database connection is successful ...") +} + +func handlers() { + r := mux.NewRouter() + + r.HandleFunc("/", EntryPoint) + r.HandleFunc("/users", user_service.GetAllUsers).Methods("GET") + r.HandleFunc("/user/{username}", user_service.GetUserByUserName).Methods("GET") + r.HandleFunc("/user", user_service.AddNewUser).Methods("POST") + r.HandleFunc("/user", user_service.UpdateUser).Methods("PUT") + r.HandleFunc("/user/{username}", user_service.DeleteUser).Methods("DELETE") + + r.HandleFunc("/user/{username}/order", user_service.CreateNewOrderByUserName).Methods("POST") + r.HandleFunc("/user/{username}/orders", user_service.GetAllOrdersByUserName).Methods("GET") + r.HandleFunc("/user/{username}/order/{orderid}", user_service.GetOrderByUserNameOrderID).Methods("GET") + r.HandleFunc("/user/{username}/order", user_service.UpdateOrderByUserName).Methods("PUT") + r.HandleFunc("/user/{username}/order/{orderid}", user_service.DeleteOrderByUserName).Methods("DELETE") + + fmt.Println("server started and running on port 8080 ...") + http.ListenAndServe(":8080", r) +} + +func EntryPoint(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode("Default Route") +} diff --git a/assignment-4/model/order.go b/assignment-4/model/order.go new file mode 100644 index 0000000..4891860 --- /dev/null +++ b/assignment-4/model/order.go @@ -0,0 +1,12 @@ +package model + +import "time" + +type Order struct { + OrderID int `json:"order_id"` + OrderDesc string `json:"order_desc"` + UserName string `json:"username"` + Amount float64 `json:"amount"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} diff --git a/assignment-4/model/user.go b/assignment-4/model/user.go new file mode 100644 index 0000000..a844ce4 --- /dev/null +++ b/assignment-4/model/user.go @@ -0,0 +1,11 @@ +package model + +import "time" + +type User struct { + UserName string `json:"username"` + PhoneNumber string `json:"phonenumber"` + City string `json:"city"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} diff --git a/assignment-4/repository/order_repository.go b/assignment-4/repository/order_repository.go new file mode 100644 index 0000000..409e78c --- /dev/null +++ b/assignment-4/repository/order_repository.go @@ -0,0 +1,104 @@ +package repository + +import ( + "time" + + "github.com/practice/db" + "github.com/practice/model" +) + +const ( + getOrderByUserNameAndOrderID = `SELECT order_id, order_desc, username, amount, created_at, updated_at FROM ORDERS WHERE username=$1 AND order_id=$2` + getAllOrdersByUserName = `SELECT order_id, order_desc, username, amount, created_at, updated_at FROM ORDERS WHERE username=$1` + insertOrderByUserName = `INSERT INTO ORDERS (order_id, order_desc, username, amount, created_at, updated_at) VALUES ($1, $2, $3, $4, now(), now()) RETURNING order_id, order_desc, username, amount, created_at, updated_at` + updateOrderByUserNameAndOrderID = `UPDATE ORDERS SET order_desc = $3, amount = $4, updated_at = now() where username = $1 AND order_id = $2 RETURNING order_id, order_desc, username, amount, created_at, updated_at` + deleteOrderByUserNameAndOrderID = `DELETE FROM ORDERS WHERE username = $1 AND order_id = $2` +) + +func DeleteOrderByUserNameAndOrderID(username string, orderID int) error { + _, err := db.GetDB().Exec(deleteOrderByUserNameAndOrderID, username, orderID) + return err +} + +func UpdateUserByUserNameAndOrderID(order model.Order) (model.Order, error) { + + var updatedOrder model.Order + + err := db.GetDB().QueryRow(updateOrderByUserNameAndOrderID, order.UserName, order.OrderID, order.OrderDesc, order.Amount).Scan(&updatedOrder.OrderID, &updatedOrder.OrderDesc, &updatedOrder.UserName, &updatedOrder.Amount, &updatedOrder.CreatedAt, &updatedOrder.UpdatedAt) + if err != nil { + return model.Order{}, err + } + + return updatedOrder, nil +} + +func CreateNewOrderByUserName(order model.Order) (model.Order, error) { + + var orderCreated model.Order + + err := db.GetDB().QueryRow(insertOrderByUserName, order.OrderID, order.OrderDesc, order.UserName, order.Amount).Scan(&orderCreated.OrderID, &orderCreated.OrderDesc, &orderCreated.UserName, &orderCreated.Amount, &orderCreated.CreatedAt, &orderCreated.UpdatedAt) + if err != nil { + return model.Order{}, err + } + + return orderCreated, nil +} + +func GetAllOrdersByUserName(username string) ([]model.Order, error) { + + var orders []model.Order + var orderDesc string + var amount float64 + var orderID int + var created_at, updated_at time.Time + + rows, err := db.GetDB().Query(getAllOrdersByUserName, username) + if err != nil { + return nil, err + } + + for rows.Next() { + err = rows.Scan(&orderID, &orderDesc, &username, &amount, &created_at, &updated_at) + if err != nil { + return nil, err + } + order := model.Order{ + OrderID: orderID, + OrderDesc: orderDesc, + UserName: username, + Amount: amount, + CreatedAt: created_at, + UpdatedAt: updated_at, + } + orders = append(orders, order) + } + + err = rows.Err() + if err != nil { + return nil, err + } + return orders, nil +} + +func GetOrderByUserNameAndOrderID(username string, orderID int) (model.Order, error) { + + var orderDesc string + var amount float64 + var created_at, updated_at time.Time + + row := db.GetDB().QueryRow(getOrderByUserNameAndOrderID, username, orderID) + err := row.Scan(&orderID, &orderDesc, &username, &amount, &created_at, &updated_at) + if err != nil { + return model.Order{}, err + } + order := model.Order{ + OrderID: orderID, + OrderDesc: orderDesc, + UserName: username, + Amount: amount, + CreatedAt: created_at, + UpdatedAt: updated_at, + } + return order, nil + +} diff --git a/assignment-4/repository/user_repository.go b/assignment-4/repository/user_repository.go new file mode 100644 index 0000000..e202857 --- /dev/null +++ b/assignment-4/repository/user_repository.go @@ -0,0 +1,98 @@ +package repository + +import ( + "time" + + "github.com/practice/db" + "github.com/practice/model" +) + +const ( + getUserByUserName = `SELECT phonenumber, city, created_at, updated_at FROM USERS WHERE username=$1` + getAllUsers = `SELECT username, phonenumber, city, created_at, updated_at FROM USERS` + insertUser = `INSERT INTO USERS (username, phonenumber, city, created_at, updated_at) VALUES ($1, $2, $3, now(), now()) RETURNING username, phonenumber, city, created_at, updated_at` + updateUserByUserName = `UPDATE USERS SET phonenumber = $2, city = $3, updated_at = now() where username = $1 RETURNING username, phonenumber, city, created_at, updated_at` + deleteUserByUserName = `DELETE FROM USERS WHERE username = $1` +) + +func DeleteUserByUserName(username string) error { + _, err := db.GetDB().Exec(deleteUserByUserName, username) + return err +} + +func UpdateUserByUserName(user model.User) (model.User, error) { + + var updatedUser model.User + + err := db.GetDB().QueryRow(updateUserByUserName, user.UserName, user.PhoneNumber, user.City).Scan(&updatedUser.UserName, &updatedUser.PhoneNumber, &updatedUser.City, &updatedUser.CreatedAt, &updatedUser.UpdatedAt) + if err != nil { + return model.User{}, err + } + + return updatedUser, nil +} + +func AddNewUser(user model.User) (model.User, error) { + + var userCreated model.User + + err := db.GetDB().QueryRow(insertUser, user.UserName, user.PhoneNumber, user.City).Scan(&userCreated.UserName, &userCreated.PhoneNumber, &userCreated.City, &userCreated.CreatedAt, &userCreated.UpdatedAt) + if err != nil { + return model.User{}, err + } + + return userCreated, nil +} + +func GetAllUsers() ([]model.User, error) { + + var users []model.User + var username, phonenumber, city string + var created_at, updated_at time.Time + + rows, err := db.GetDB().Query(getAllUsers) + if err != nil { + return nil, err + } + + for rows.Next() { + err = rows.Scan(&username, &phonenumber, &city, &created_at, &updated_at) + if err != nil { + return nil, err + } + user := model.User{ + UserName: username, + PhoneNumber: phonenumber, + City: city, + CreatedAt: created_at, + UpdatedAt: updated_at, + } + users = append(users, user) + } + + err = rows.Err() + if err != nil { + return nil, err + } + return users, nil +} + +func GetUserByUserName(username string) (model.User, error) { + + var phonenumber, city string + var created_at, updated_at time.Time + row := db.GetDB().QueryRow(getUserByUserName, username) + err := row.Scan(&phonenumber, &city, &created_at, &updated_at) + if err != nil { + return model.User{}, err + } + user := model.User{ + UserName: username, + PhoneNumber: phonenumber, + City: city, + CreatedAt: created_at, + UpdatedAt: updated_at, + } + return user, nil + +} diff --git a/assignment-4/service/order_service/order_service.go b/assignment-4/service/order_service/order_service.go new file mode 100644 index 0000000..f31e7a6 --- /dev/null +++ b/assignment-4/service/order_service/order_service.go @@ -0,0 +1,41 @@ +package orderservice + +import ( + "github.com/practice/model" + "github.com/practice/repository" +) + +func CreateNewOrder(username string, order model.Order) (model.Order, error) { + order.UserName = username + createdOrder, err := repository.CreateNewOrderByUserName(order) + return createdOrder, err +} + +func GetOrderByUserNameOrderID(username string, orderID int) (model.Order, error) { + order, err := repository.GetOrderByUserNameAndOrderID(username, orderID) + return order, err +} + +func GetAllOrders(username string) ([]model.Order, error) { + orders, err := repository.GetAllOrdersByUserName(username) + return orders, err +} + +func UpdateOrder(order model.Order) (model.Order, error) { + + _, err := repository.GetOrderByUserNameAndOrderID(order.UserName, order.OrderID) + if err != nil { + return model.Order{}, err + } + updatedOrder, err := repository.UpdateUserByUserNameAndOrderID(order) + return updatedOrder, err +} + +func DeleteOrder(username string, orderID int) error { + _, err := repository.GetOrderByUserNameAndOrderID(username, orderID) + if err != nil { + return err + } + err = repository.DeleteOrderByUserNameAndOrderID(username, orderID) + return err +} diff --git a/assignment-4/service/user_service/user_impl.go b/assignment-4/service/user_service/user_impl.go new file mode 100644 index 0000000..77630f6 --- /dev/null +++ b/assignment-4/service/user_service/user_impl.go @@ -0,0 +1,48 @@ +package user_service + +import ( + "github.com/practice/model" + "github.com/practice/repository" +) + +func getAllUsers() ([]model.User, error) { + users, err := repository.GetAllUsers() + return users, err +} + +func getUserByUserName(username string) (model.User, error) { + user, err := repository.GetUserByUserName(username) + return user, err +} + +func addNewUser(user model.User) (model.User, error) { + userCreated, err := repository.AddNewUser(user) + return userCreated, err +} + +func updateUser(user model.User) (model.User, error) { + oldUser, err := getUserByUserName(user.UserName) + if err != nil { + return model.User{}, err + } + if user.PhoneNumber == "" { + user.PhoneNumber = oldUser.PhoneNumber + } + if user.City == "" { + user.City = oldUser.City + } + updatedUser, err := repository.UpdateUserByUserName(user) + if err != nil { + return model.User{}, err + } + return updatedUser, nil +} + +func deleteUser(username string) error { + _, err := getUserByUserName(username) + if err != nil { + return err + } + err = repository.DeleteUserByUserName(username) + return err +} diff --git a/assignment-4/service/user_service/user_service.go b/assignment-4/service/user_service/user_service.go new file mode 100644 index 0000000..237ff12 --- /dev/null +++ b/assignment-4/service/user_service/user_service.go @@ -0,0 +1,320 @@ +package user_service + +import ( + "database/sql" + "encoding/json" + "net/http" + "strconv" + + "github.com/gorilla/mux" + "github.com/practice/model" + orderservice "github.com/practice/service/order_service" +) + +func GetAllUsers(w http.ResponseWriter, r *http.Request) { + users, err := getAllUsers() + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusNoContent) + json.NewEncoder(w).Encode("No user data found") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(users) +} + +func GetUserByUserName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + username := vars["username"] + user, err := getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusNoContent) + json.NewEncoder(w).Encode("Err: user not found with username: " + username) + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(user) +} + +func AddNewUser(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + var user model.User + _ = json.NewDecoder(r.Body).Decode(&user) + + if user.UserName == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field can't be empty") + return + } + if user.PhoneNumber == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("phonenumber field can't be empty") + return + } + if user.City == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("city field can't be empty") + return + } + + userCreated, err := addNewUser(user) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(userCreated) + +} + +func UpdateUser(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Content-Type", "application/json") + var user model.User + _ = json.NewDecoder(r.Body).Decode(&user) + + if user.UserName == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field can't be empty") + return + } + + updatedUser, err := updateUser(user) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user not found") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(updatedUser) + +} + +func DeleteUser(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + username := vars["username"] + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + + err := deleteUser(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode("user successfully deleted") +} + +func CreateNewOrderByUserName(w http.ResponseWriter, r *http.Request) { + + w.Header().Set("Content-Type", "application/json") + vars := mux.Vars(r) + username := vars["username"] + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + + _, err := getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + var order model.Order + json.NewDecoder(r.Body).Decode(&order) + + createdOrder, err := orderservice.CreateNewOrder(username, order) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(createdOrder) +} + +func GetAllOrdersByUserName(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + username := vars["username"] + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + + _, err := getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + orders, err := orderservice.GetAllOrders(username) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(orders) + +} + +func GetOrderByUserNameOrderID(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + username := vars["username"] + orderID, err := strconv.Atoi(vars["orderid"]) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + _, err = getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + order, err := orderservice.GetOrderByUserNameOrderID(username, orderID) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode(order) +} + +func UpdateOrderByUserName(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + vars := mux.Vars(r) + username := vars["username"] + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + + _, err := getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + var order model.Order + json.NewDecoder(r.Body).Decode(&order) + + updatedOrder, err := orderservice.UpdateOrder(order) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusCreated) + json.NewEncoder(w).Encode(updatedOrder) +} + +func DeleteOrderByUserName(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + username := vars["username"] + orderID, err := strconv.Atoi(vars["orderid"]) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + if username == "" { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("username field cannot be empty") + return + } + _, err = getUserByUserName(username) + if err != nil { + if err == sql.ErrNoRows { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("user does not exists") + return + } + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + err = orderservice.DeleteOrder(username, orderID) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + json.NewEncoder(w).Encode(err.Error()) + return + } + + w.WriteHeader(http.StatusOK) + json.NewEncoder(w).Encode("order details deleted successfuly") +}