diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 23caa3a..6bfef78 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -4,21 +4,16 @@ on: push: pull_request: -jobs: +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} +jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Login to Docker Hub - uses: docker/login-action@v1 - with: - password: ${{ secrets.HUB_DOCKER_TOKEN }} - username: ${{ secrets.DOCKER_HUB_USERNAME }} - ecr: false - logout: true - - name: Set up Go uses: actions/setup-go@v2 with: @@ -29,3 +24,33 @@ jobs: - name: Test run: go test -v ./... + + + push_to_registry: + name: Push Docker image to Docker Hub + needs: build + runs-on: ubuntu-latest + steps: + - name: Check out the repo + uses: actions/checkout@v2 + + - name: Log in to Docker Hub + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.HUB_DOCKER_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: arngrimur/computersaysno_welcome + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + diff --git a/.gitignore b/.gitignore index 56d9ca8..2cc2524 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ .idea *.iml computersaysno +csn diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..dfe992c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,44 @@ +# syntax=docker/dockerfile:1 + +## +## Build +## +FROM golang:1.17.6-alpine3.15 AS build +ENV USER=nonroot +ENV UID=10001 + +RUN apk update && apk add --no-cache git +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + "${USER}" + +WORKDIR /go/src + +COPY . ./ + +RUN go mod download +RUN go mod tidy +RUN GOOS=linux CGO_ENABLED=0 GOARCH=amd64 go build -ldflags "-s -w" -o /csn + +## +## Deploy +## +FROM scratch +LABEL arch="amd64" + +WORKDIR / + +COPY --from=build /csn /csn +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group + +EXPOSE 443 + +USER nonroot:nonroot + +ENTRYPOINT ["/csn"] \ No newline at end of file diff --git a/RESTendpoints/welcome.go b/RESTendpoints/welcome.go index a936758..a919210 100644 --- a/RESTendpoints/welcome.go +++ b/RESTendpoints/welcome.go @@ -12,15 +12,12 @@ type WelcomeModel struct { DB *sql.DB } -//var lookUpMap = make(map[string]*models.IpRecord) - func (welcome *WelcomeModel) Welcome(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/plain") ip, _, err := net.SplitHostPort(r.RemoteAddr) if err != nil { ip = r.RemoteAddr } - //ipEntry, ipEntryExist := lookUpMap[ip] findIpRecord := models.NewIpRecord(ip) readIpRecord, err := findIpRecord.Read(welcome.DB) if err != nil { @@ -31,15 +28,6 @@ func (welcome *WelcomeModel) Welcome(w http.ResponseWriter, r *http.Request) { readIpRecord.Update(welcome.DB) generateOutput(w, readIpRecord) } - - //if ipEntryExist { - // ipEntry.IncreaseHitCount() - // generateOutput(w, ipEntry) - //} else { - // lookUpMap[ip] = models.NewIpRecord(ip) - // //save(lookUpMap[ip]) - // generateOutput(w, lookUpMap[ip]) - //} } func generateOutput(w http.ResponseWriter, entry *models.IpRecord) { @@ -57,4 +45,5 @@ func generateOutput(w http.ResponseWriter, entry *models.IpRecord) { _, _ = fmt.Fprintf(w, "The computer says NO!!!") break } + } diff --git a/RESTendpoints/welcome_test.go b/RESTendpoints/welcome_test.go index 0443106..7a28540 100644 --- a/RESTendpoints/welcome_test.go +++ b/RESTendpoints/welcome_test.go @@ -15,19 +15,8 @@ func TestWelcome(t *testing.T) { m WelcomeModel status int } - var testDbConfig = database_test_helper.DbConfig{ - DbSecrets: database_test_helper.DbSecrets{ - DatabaseUser: "testuser", - DatabasePassword: "testpassword", - }, - HostConfig: database_test_helper.HostConfig{ - AutoRemove: true, - RestartPolicy: "no", - }, - ExpireTime: uint(5000), - DatabaseName: "csn_db", - } - var connString, pool, resource = database_test_helper.SetupDatbase(testDbConfig) + + var connString, pool, resource = database_test_helper.SetupDatbase() defer database_test_helper.Purge(pool, resource) var sqlDb, err = database_test_helper.InitDatabase(*connString) require.NoError(t, err, "Could not set up database") @@ -40,7 +29,7 @@ func TestWelcome(t *testing.T) { {"Second time is ok", args{getRequest(t, "GET", "/", "127.0.0.1"), WelcomeModel{DB: sqlDb}, http.StatusOK}}, {"Third time is forbidden", args{getRequest(t, "GET", "/", "127.0.0.1"), WelcomeModel{DB: sqlDb}, http.StatusForbidden}}, {"Keep rejecting", args{getRequest(t, "GET", "/", "127.0.0.1"), WelcomeModel{DB: sqlDb}, http.StatusForbidden}}, - {"New IP is alllowed", args{getRequest(t, "GET", "/", "10.0.0.10"), WelcomeModel{DB: sqlDb}, http.StatusOK}}, + {"New IP is allowed", args{getRequest(t, "GET", "/", "10.0.0.10"), WelcomeModel{DB: sqlDb}, http.StatusOK}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { diff --git a/database_test_helper/datastore.go b/database_test_helper/datastore.go index 0599de9..77670d1 100644 --- a/database_test_helper/datastore.go +++ b/database_test_helper/datastore.go @@ -39,13 +39,25 @@ type DbConfig struct { var db *sql.DB var connectionsString string +var TestDbConfig = DbConfig{ + DbSecrets: DbSecrets{ + DatabaseUser: "testuser", + DatabasePassword: "testpassword", + }, + HostConfig: HostConfig{ + AutoRemove: true, + RestartPolicy: "no", + }, + ExpireTime: uint(120), + DatabaseName: "csn_db", +} -func SetupDatbase(dbConfig DbConfig) (*string, *dockertest.Pool, *dockertest.Resource) { +func SetupDatbase() (*string, *dockertest.Pool, *dockertest.Resource) { pool, err := dockertest.NewPool("") // uses a sensible default on windows (tcp/http) and linux/osx (socket) // pulls an image, creates a container based on it and runs it - pool.MaxWait = time.Duration(dbConfig.ExpireTime) * time.Second + pool.MaxWait = time.Duration(TestDbConfig.ExpireTime) * time.Second if err != nil { log.Fatalf("Could not connect to docker: %s", err) } @@ -55,22 +67,22 @@ func SetupDatbase(dbConfig DbConfig) (*string, *dockertest.Pool, *dockertest.Res Repository: "postgres", Tag: "14.1", Env: []string{ - "POSTGRES_USER=" + dbConfig.DbSecrets.DatabaseUser, - "POSTGRES_PASSWORD=" + dbConfig.DbSecrets.DatabasePassword, - "POSTGRES_DB=" + dbConfig.DatabaseName, + "POSTGRES_USER=" + TestDbConfig.DbSecrets.DatabaseUser, + "POSTGRES_PASSWORD=" + TestDbConfig.DbSecrets.DatabasePassword, + "POSTGRES_DB=" + TestDbConfig.DatabaseName, }, Mounts: []string{workingDir + "/mounts:/docker-entrypoint-initdb.d"}, }, func(config *docker.HostConfig) { - config.AutoRemove = dbConfig.HostConfig.AutoRemove - config.RestartPolicy = docker.RestartPolicy{Name: dbConfig.HostConfig.RestartPolicy} + config.AutoRemove = TestDbConfig.HostConfig.AutoRemove + config.RestartPolicy = docker.RestartPolicy{Name: TestDbConfig.HostConfig.RestartPolicy} }) if err != nil { log.Fatalf("Could not start resource: %s", err) } - resource.Expire(dbConfig.ExpireTime) // Tell docker to hard kill the container + resource.Expire(TestDbConfig.ExpireTime) // Tell docker to hard kill the container - connectionsString = buildConnectionString(&dbConfig, resource) - pool.MaxWait = time.Duration(dbConfig.ExpireTime) * time.Second + connectionsString = buildConnectionString(&TestDbConfig, resource) + pool.MaxWait = time.Duration(TestDbConfig.ExpireTime) * time.Second // exponential backoff-retry, because the application in the container might not be ready to accept connections yet waitForConnection(err, pool, connectionsString) return &connectionsString, pool, resource diff --git a/database_test_helper/datastore_test.go b/database_test_helper/datastore_test.go index 301c0ad..fda747f 100644 --- a/database_test_helper/datastore_test.go +++ b/database_test_helper/datastore_test.go @@ -7,24 +7,13 @@ import ( ) func TestInit(t *testing.T) { - var testDbConfig = DbConfig{ - DbSecrets: DbSecrets{ - DatabaseUser: "testuser", - DatabasePassword: "testpassword", - }, - HostConfig: HostConfig{ - AutoRemove: true, - RestartPolicy: "no", - }, - ExpireTime: uint(120), - DatabaseName: "csn_db", - } - connectionString, pool, resource := SetupDatbase(testDbConfig) + + connectionString, pool, resource := SetupDatbase() t.Cleanup(func() { Purge(pool, resource) }) - assert.Regexp(t, "^postgres://testuser:testpassword@((\\d){1,3}\\.){3}\\d{1,3}:?(\\d){0,5}\\/"+testDbConfig.DatabaseName+"\\?sslmode=disable$", *connectionString) + assert.Regexp(t, "^postgres://testuser:testpassword@((\\d){1,3}\\.){3}\\d{1,3}:?(\\d){0,5}\\/"+TestDbConfig.DatabaseName+"\\?sslmode=disable$", *connectionString) db, initErr := InitDatabase(*connectionString) require.NoError(t, initErr, "Could not init the database") dbErr := db.Ping() diff --git a/db/database.go b/db/database.go index 5d51978..13dca3e 100644 --- a/db/database.go +++ b/db/database.go @@ -18,7 +18,7 @@ func InitDatabase() (*sql.DB, error) { } driver, driverErr := postgres.WithInstance(db, &postgres.Config{}) if driverErr != nil { - log.Fatalf("Can insatnciate database") + log.Fatalf("Can not instanciate database") return nil, driverErr } m, migrateErr := migrate.NewWithDatabaseInstance( @@ -36,5 +36,6 @@ func InitDatabase() (*sql.DB, error) { } func createConnectionString() string { - panic("Implement me!!! Grab from kubenetes secets") + log.Fatalf("Implement me!!! Grab from kubenetes secets") + return "jdbc:postgresql://localhost:55144/csn_db?sslmode=disable" } diff --git a/docker/postgres/Dockerfile b/docker/postgres/Dockerfile index a03f26e..33a81a5 100644 --- a/docker/postgres/Dockerfile +++ b/docker/postgres/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1 -FROM mysql:8.0.27 +FROM postgres:8.0.27 MAINTAINER Arngrimur Bjarnason ENV MYSQL_DATABASE csn_db diff --git a/go.mod b/go.mod index 5cb056c..f16bf53 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/lib/pq v1.10.4 github.com/ory/dockertest/v3 v3.8.1 github.com/stretchr/testify v1.7.0 - ) require ( @@ -43,5 +42,10 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) - -replace golang.org/x/net => golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 +replace ( + golang.org/x/net => golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 + github.com/containerd/continuity v0.1.0 => github.com/containerd/continuity v0.2.0 + //csn/db => ./db + //csn/models => ./models + //csn/RESTendpoints => ./RESTendpoints +) \ No newline at end of file diff --git a/go.sum b/go.sum index a37cf5e..7c6f15a 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,5 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -217,8 +218,8 @@ github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/continuity v0.2.0 h1:j/9Wnn+hrEWjLvHuIxUU1YI5JjEjVlT2AA68cse9rwY= +github.com/containerd/continuity v0.2.0/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -867,6 +868,7 @@ github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= diff --git a/models/IpRecord_test.go b/models/IpRecord_test.go index 499c150..a9f8cdc 100644 --- a/models/IpRecord_test.go +++ b/models/IpRecord_test.go @@ -21,19 +21,7 @@ var lookFor = IpRecord{ } func TestMain(m *testing.M) { - var testDbConfig = database_test_helper.DbConfig{ - DbSecrets: database_test_helper.DbSecrets{ - DatabaseUser: "testuser", - DatabasePassword: "testpassword", - }, - HostConfig: database_test_helper.HostConfig{ - AutoRemove: true, - RestartPolicy: "no", - }, - ExpireTime: uint(120), - DatabaseName: "csn_db", - } - connString, pool, resource = database_test_helper.SetupDatbase(testDbConfig) + connString, pool, resource = database_test_helper.SetupDatbase() var err error sqlDb, err = database_test_helper.InitDatabase(*connString) if err != nil {