From 3ceba1a11781c75633d779296c1567fa9d74cccc Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Tue, 13 Jan 2026 20:09:19 +1100 Subject: [PATCH] add rpm generation code --- .drone.yml | 18 ++- README.md | 234 ++-------------------------- components/core/header.templ | 75 ++++++++- components/core/header_templ.go | 4 +- components/views/index.templ | 47 ++++-- components/views/index_templ.go | 14 +- components/views/snapshots.templ | 34 ++-- components/views/snapshots_templ.go | 59 ++++--- db/querier.go | 12 +- scripts/drone.sh | 4 +- server/handler/vmImport.go | 1 - server/handler/vmModifyEvent.go | 8 +- server/handler/vmMoveEvent.go | 4 +- sqlc.yml | 6 +- src/postinstall.sh | 10 ++ src/postremove.sh | 8 + src/preinstall.sh | 45 ++++++ src/preremove.sh | 8 + src/vctp.default | 1 + src/vctp.service | 21 +++ src/vctp.yml | 25 +++ vctp.yml | 40 +++++ 22 files changed, 388 insertions(+), 290 deletions(-) create mode 100644 src/postinstall.sh create mode 100644 src/postremove.sh create mode 100644 src/preinstall.sh create mode 100644 src/preremove.sh create mode 100644 src/vctp.default create mode 100644 src/vctp.service create mode 100644 src/vctp.yml create mode 100644 vctp.yml diff --git a/.drone.yml b/.drone.yml index 000517a..54f0be4 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,6 +17,7 @@ steps: mount: - pkg.mod - pkg.build + - pkg.tools volumes: - name: cache path: /go @@ -36,13 +37,27 @@ steps: - go install github.com/a-h/templ/cmd/templ@latest - go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest - go install github.com/swaggo/swag/cmd/swag@latest + - go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest - sqlc generate - templ generate -path ./components - swag init --exclude "pkg.mod,pkg.build,pkg.tools" -o server/router/docs - chmod +x ./scripts/*.sh - ./scripts/update-swagger-ui.sh - ./scripts/drone.sh - - cp ./build/cbs-linux-amd64 /shared/ + - cp ./build/vctp-linux-amd64 /shared/ + +- name: rpm + image: ghcr.io/goreleaser/nfpm + environment: + TZ: UTC + volumes: + - name: shared + path: /shared + commands: + - cp /shared/vctp-linux-amd64 ./build/vctp-linux-amd64 + #- find . + - nfpm package --config vctp.yml --packager rpm --target ./build/ + - ls -lah ./build/ - name: dell-sftp-deploy image: hypervtechnics/drone-sftp @@ -76,6 +91,7 @@ steps: mount: - pkg.mod - pkg.build + - pkg.tools volumes: - name: cache path: /go diff --git a/README.md b/README.md index 283019b..8ce5c37 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,14 @@ -# Go + HTMX Template +# Initial setup -This is built from the template https://github.com/Piszmog/go-htmx-template that comes with everything you need to build a Web Application using Go (templ) and HTMX. - -The template comes with a basic structure of using a SQL DB (`sqlc`), E2E testing (playwright), and styling (tailwindcss). - -## Getting Started - -Clone https://github.com/Piszmog/go-htmx-template - -Once cloned, run the `update_module.sh` script to change the module to your module name. +## Pre-requisite tools ```shell -./update_module my-new-module +go install github.com/a-h/templ/cmd/templ@latest +go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest +go install github.com/swaggo/swag/cmd/swag@latest ``` -## Technologies - -A few different technologies are configured to help getting off the ground easier. - -- [sqlc](https://sqlc.dev/) for database layer - - Stubbed to use SQLite - - This can be easily swapped with [sqlx](https://jmoiron.github.io/sqlx/) - - The script `upgrade_sqlc.sh` is available to upgrade GitHub Workflow files to latest sqlc version -- [Tailwind CSS](https://tailwindcss.com/) for styling - - Output is generated with the [CLI](https://tailwindcss.com/docs/installation) -- [templ](https://templ.guide/) for creating HTML - - The script `upgrade_templ.sh` is available to make upgrading easier -- [HTMX](https://htmx.org/) for HTML interaction - - The script `upgrade_htmx.sh` is available to make upgrading easier -- [goose](https://github.com/pressly/goose) for DB migrations - -TODO: investigate https://github.com/DATA-DOG/go-sqlmock for testing - -Technologies we're no longer using: -- [golang migrate](https://github.com/golang-migrate/migrate) for DB migrations -- [playwright-go](https://github.com/playwright-community/playwright-go) for E2E testing. - -Everything else uses the standard library. - -## Structure -(Now out of date) - -```text -. -├── Makefile -├── components -│   ├── core -│   │   └── html.templ -│   └── home -│   └── home.templ -├── db -│   ├── db.go -│   ├── local.go -│   ├── migrations -│   │   ├── 20240407203525_init.down.sql -│   │   └── 20240407203525_init.up.sql -│   └── queries -│   └── query.sql -├── db.sqlite3 -├── dist -│   ├── assets -│   │   └── js -│   │   └── htmx@1.9.10.min.js -│   └── dist.go -├── e2e -│   ├── e2e_test.go -│   ├── home_test.go -│   └── testdata -│   └── seed.sql -├── go.mod -├── go.sum -├── log -│   └── log.go -├── main.go -├── server -│   ├── handler -│   │   ├── handler.go -│   │   └── home.go -│   ├── middleware -│   │   ├── cache.go -│   │   ├── logging.go -│   │   └── middleware.go -│   ├── router -│   │   └── router.go -│   └── server.go -├── sqlc.yml -├── styles -│   └── input.css -├── tailwind.config.js -└── version - └── version.go -``` - -### Components - -This is where `templ` files live. Anything you want to render to the user goes here. Note, all -`*.go` files will be ignored by `git` (configured in `.gitignore`). - -### DB - -This is the directory that `sqlc` generates to. Update `queries.sql` to build -your database operations. The schema for `sqlc` lives in `db/schema.sql`. - -Once `queries.sql` is updated, run `make generate-sql` to update the generated models - -#### DB Migrations +## Database This project now uses [goose](https://github.com/pressly/goose) for DB migrations. Install via `brew install goose` on a mac, or install via golang with command `go install github.com/pressly/goose/v3/cmd/goose@latest` @@ -114,6 +18,16 @@ Create a new up/down migration file with this command goose -dir db/migrations sqlite3 ./db.sqlite3 create init sql ``` +```shell +sqlc generate +``` + +## HTML templates +Run `templ generate -path ./components` to generate code based on template files + +## Documentation +Run `swag init --exclude "pkg.mod,pkg.build,pkg.tools" -o server/router/docs` + #### Database Configuration By default the app uses SQLite and creates/opens `db.sqlite3`. You can opt into PostgreSQL by setting environment variables: @@ -137,118 +51,4 @@ PostgreSQL migrations live in `db/migrations_postgres`, while SQLite migrations Hourly and daily snapshot table retention can be configured with environment variables: - `HOURLY_SNAPSHOT_MAX_AGE_DAYS` (default: 60) -- `DAILY_SNAPSHOT_MAX_AGE_MONTHS` (default: 12) - -### Dist - -This is where your assets live. Any Javascript, images, or styling needs to go in the -`dist/assets` directory. The directory will be embedded into the application. - -Note, the `dist/assets/css` will be ignored by `git` (configured in `.gitignore`) since the -files that are written to this directory are done by the Tailwind CSS CLI. Custom styles should -go in the `styles/input.css` file. - -### E2E - -To test the UI, the `e2e` directory contains the Go tests for performing End to end testing. To -run the tests, run the command - -```shell -go test -v ./... -tags=e2e -``` - -The end to end tests, will start up the app, on a random port, seeding the database using the -`seed.sql` file. Once the tests are complete, the app will be stopped. - -The E2E tests use Playwright (Go) for better integration into the Go tooling. - -### Log - -This contains helper function to create a `slog.Logger`. Log level and output type can be set -with then environment variables `LOG_LEVEL` and `LOG_OUTPUT`. The logger will write to -`stdout`. - -### Server - -This contains everything related to the HTTP server. It comes with a graceful shutdown handler -that handles `SIGINT`. - -#### Router - -This package sets up the routing for the application, such as the `/assets/` path and `/` path. -It uses the standard libraries mux for routing. You can easily swap out for other HTTP -routers such as [gorilla/mux](https://github.com/gorilla/mux). - -#### Middleware - -This package contains any middleware to configured with routes. - -#### Handler - -This package contains the handler to handle the actual routes. - -#### Styles - -This contains the `input.css` that the Tailwind CSS CLI uses to generate your output CSS. -Update `input.css` with any custom CSS you need and it will be included in the output CSS. - -#### Version - -This package allows you to set a version at build time. If not set, the version defaults to -`dev`. To set the version run the following command, - -```shell -go build -o ./app -ldflags="-X version.Value=1.0.0" -``` - -See the `Makefile` for building the application. - -## Run - -There are a couple builtin ways to run the application - using `air` or the `Makefile` helper -commands. - -### Prerequisites - -- Install [templ](https://templ.guide/quick-start/installation) - `go install github.com/a-h/templ/cmd/templ@latest` -- Install [sqlc](https://docs.sqlc.dev/en/stable/overview/install.html) -- Install [tailwindcss CLI](https://tailwindcss.com/docs/installation) - -#### tailwindcss -```shell -# Example for macOS arm64 -curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64 -chmod +x tailwindcss-macos-arm64 -sudo mv tailwindcss-macos-arm64 /usr/local/bin/tailwindcss -``` - -### Makefile - -You can also run with the provided `Makefile`. There are commands to generate `templ` files and -tailwind output css. - -```shell -# Generate and watch templ -make generate-templ-watch - -# Genrate and watch tailwindcss -make generate-tailwind-watch - -# Run application -make run -``` - -## Github Workflow - -The repository comes with two Github workflows as well. One called `ci.yml` that lints and -tests your code. The other called `release.yml` that creates a tag, GitHub Release, and -attaches the Linux binary to the Release. - -Note, the version of `github.com/a-h/templ/cmd/templ` matches the version in `go.mod`. If these -do not match, the build will fail. When upgrading your `templ` version, make sure to update -`ci.yml` and `release.yml`. - -### GoReleaser - -If you need to compile for more than Linux, see [GoReleaser](https://goreleaser.com/) for a -better release process. +- `DAILY_SNAPSHOT_MAX_AGE_MONTHS` (default: 12) \ No newline at end of file diff --git a/components/core/header.templ b/components/core/header.templ index 0e7e0d8..4fa9e63 100644 --- a/components/core/header.templ +++ b/components/core/header.templ @@ -10,5 +10,78 @@ templ Header() { vCTP API + -} \ No newline at end of file +} diff --git a/components/core/header_templ.go b/components/core/header_templ.go index 993badd..4c35c84 100644 --- a/components/core/header_templ.go +++ b/components/core/header_templ.go @@ -38,13 +38,13 @@ func Header() templ.Component { var templ_7745c5c3_Var2 templ.SafeURL templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinURLErrs("/assets/css/output@" + version.Value + ".css") if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/core/header.templ`, Line: 12, Col: 61} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `core/header.templ`, Line: 12, Col: 61} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" rel=\"stylesheet\">") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" rel=\"stylesheet\">") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/components/views/index.templ b/components/views/index.templ index 71a1d6d..297b24e 100644 --- a/components/views/index.templ +++ b/components/views/index.templ @@ -14,16 +14,39 @@ templ Index(info BuildInfo) { @core.Header() - -
-
-

Build Information

-

Build Time: {info.BuildTime}

-

SHA1 Version: {info.SHA1Ver}

-

Go Runtime Version: {info.GoVersion}

-
-
- - @core.Footer() + +
+
+
+
+
vCTP Console
+

Build Intelligence Dashboard

+

A glossy, snapshot-ready view of what is running.

+
+ +
+
+ +
+
+

Build Time

+

{info.BuildTime}

+
+
+

SHA1 Version

+

{info.SHA1Ver}

+
+
+

Go Runtime

+

{info.GoVersion}

+
+
+
+ + @core.Footer() -} \ No newline at end of file +} diff --git a/components/views/index_templ.go b/components/views/index_templ.go index 7e67c0d..ab254a3 100644 --- a/components/views/index_templ.go +++ b/components/views/index_templ.go @@ -47,46 +47,46 @@ func Index(info BuildInfo) templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

Build Information

Build Time: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

vCTP Console

Build Intelligence Dashboard

A glossy, snapshot-ready view of what is running.

Build Time

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var2 string templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(info.BuildTime) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 21, Col: 80} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 37, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

SHA1 Version: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

SHA1 Version

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var3 string templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(info.SHA1Ver) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 22, Col: 80} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 41, Col: 57} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Go Runtime Version: ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Go Runtime

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var4 string templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(info.GoVersion) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/index.templ`, Line: 23, Col: 88} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/index.templ`, Line: 45, Col: 59} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/components/views/snapshots.templ b/components/views/snapshots.templ index 0d8b932..c67d3a6 100644 --- a/components/views/snapshots.templ +++ b/components/views/snapshots.templ @@ -25,21 +25,33 @@ templ SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) { @core.Header() - -
-
-

{title}

-

{subtitle}

-
+
@core.Footer() diff --git a/components/views/snapshots_templ.go b/components/views/snapshots_templ.go index f11a2a8..5c88cdc 100644 --- a/components/views/snapshots_templ.go +++ b/components/views/snapshots_templ.go @@ -133,69 +133,82 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "
Snapshot Library

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var5 string templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 31, Col: 42} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 34, Col: 49} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "

") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var6 string templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/views/snapshots.templ`, Line: 32, Col: 44} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 35, Col: 51} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

    ") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "

Back to Dashboard

Available Exports

") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var7 string + templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(len(entries)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 44, Col: 83} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " files
") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -203,7 +216,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "") + templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/db/querier.go b/db/querier.go index d292ba2..eef54e5 100644 --- a/db/querier.go +++ b/db/querier.go @@ -10,10 +10,10 @@ import ( type Querier interface { CleanupUpdates(ctx context.Context, arg queries.CleanupUpdatesParams) error CleanupUpdatesNullVm(ctx context.Context) error - CreateEvent(ctx context.Context, arg queries.CreateEventParams) (queries.Events, error) + CreateEvent(ctx context.Context, arg queries.CreateEventParams) (queries.Event, error) CreateInventory(ctx context.Context, arg queries.CreateInventoryParams) (queries.Inventory, error) CreateInventoryHistory(ctx context.Context, arg queries.CreateInventoryHistoryParams) (queries.InventoryHistory, error) - CreateUpdate(ctx context.Context, arg queries.CreateUpdateParams) (queries.Updates, error) + CreateUpdate(ctx context.Context, arg queries.CreateUpdateParams) (queries.Update, error) GetInventoryByName(ctx context.Context, name string) ([]queries.Inventory, error) GetInventoryByVcenter(ctx context.Context, vcenter string) ([]queries.Inventory, error) GetInventoryEventId(ctx context.Context, cloudid sql.NullString) (queries.Inventory, error) @@ -21,15 +21,15 @@ type Querier interface { GetInventoryVmId(ctx context.Context, arg queries.GetInventoryVmIdParams) (queries.Inventory, error) GetInventoryVmUuid(ctx context.Context, arg queries.GetInventoryVmUuidParams) (queries.Inventory, error) GetReportInventory(ctx context.Context) ([]queries.Inventory, error) - GetReportUpdates(ctx context.Context) ([]queries.Updates, error) - GetVmUpdates(ctx context.Context, arg queries.GetVmUpdatesParams) ([]queries.Updates, error) + GetReportUpdates(ctx context.Context) ([]queries.Update, error) + GetVmUpdates(ctx context.Context, arg queries.GetVmUpdatesParams) ([]queries.Update, error) InventoryCleanup(ctx context.Context, arg queries.InventoryCleanupParams) error InventoryCleanupTemplates(ctx context.Context) error InventoryCleanupVcenter(ctx context.Context, vc string) error InventoryMarkDeleted(ctx context.Context, arg queries.InventoryMarkDeletedParams) error InventoryUpdate(ctx context.Context, arg queries.InventoryUpdateParams) error - ListEvents(ctx context.Context) ([]queries.Events, error) + ListEvents(ctx context.Context) ([]queries.Event, error) ListInventory(ctx context.Context) ([]queries.Inventory, error) - ListUnprocessedEvents(ctx context.Context, eventtime sql.NullInt64) ([]queries.Events, error) + ListUnprocessedEvents(ctx context.Context, eventtime sql.NullInt64) ([]queries.Event, error) UpdateEventsProcessed(ctx context.Context, eid int64) error } diff --git a/scripts/drone.sh b/scripts/drone.sh index 9fc6d94..78cf3f4 100755 --- a/scripts/drone.sh +++ b/scripts/drone.sh @@ -4,6 +4,7 @@ export CGO_ENABLED=0 package_name=vctp +package=./ commit=$(git rev-parse HEAD) buildtime=$(date +%Y-%m-%dT%T%z) #Extract the version from yml @@ -16,6 +17,7 @@ echo Building:: echo - Version $package_version echo - Commit $commit echo - Build Time $buildtime +mkdir -p build for platform in "${platforms[@]}" do platform_split=(${platform//\// }) @@ -38,6 +40,6 @@ do #sha256sum build/${output_name}.gz > build/${output_name}_checksum.txt done -#nfpm package --config $package_name.yml --packager rpm --target build/ +nfpm package --config $package_name.yml --packager rpm --target build/ ls -lah build diff --git a/server/handler/vmImport.go b/server/handler/vmImport.go index 371bb65..738b6b1 100644 --- a/server/handler/vmImport.go +++ b/server/handler/vmImport.go @@ -97,5 +97,4 @@ func (h *Handler) VmImport(w http.ResponseWriter, r *http.Request) { "status": "OK", "message": fmt.Sprintf("Successfully processed import request for VM '%s'", inData.Name), }) - return } diff --git a/server/handler/vmModifyEvent.go b/server/handler/vmModifyEvent.go index 43eb063..2ff2441 100644 --- a/server/handler/vmModifyEvent.go +++ b/server/handler/vmModifyEvent.go @@ -73,7 +73,7 @@ func (h *Handler) VmModifyEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusAccepted) json.NewEncoder(w).Encode(map[string]string{ "status": "OK", - "message": fmt.Sprintf("Received update event successfully but no config changes were found"), + "message": "Received update event successfully but no config changes were found", }) return } else { @@ -178,7 +178,7 @@ func (h *Handler) VmModifyEvent(w http.ResponseWriter, r *http.Request) { } else { h.Logger.Debug("Matched regex", "disk_owner", matches[1]) - if strings.ToLower(matches[1]) == strings.ToLower(event.CloudEvent.Data.VM.Name) { + if strings.EqualFold(matches[1], event.CloudEvent.Data.VM.Name) { h.Logger.Debug("This disk belongs to this VM") changeFound = true diskChangeFound = true @@ -278,7 +278,7 @@ func (h *Handler) VmModifyEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{ "status": "OK", - "message": fmt.Sprintf("Successfully processed vm modify event"), + "message": "Successfully processed vm modify event", }) return } @@ -304,7 +304,7 @@ func (h *Handler) VmModifyEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(map[string]string{ "status": "OK", - "message": fmt.Sprintf("Successfully processed vm modify event"), + "message": "Successfully processed vm modify event", }) return } diff --git a/server/handler/vmMoveEvent.go b/server/handler/vmMoveEvent.go index fe8bc1e..f5e2c34 100644 --- a/server/handler/vmMoveEvent.go +++ b/server/handler/vmMoveEvent.go @@ -65,7 +65,7 @@ func (h *Handler) VmMoveEvent(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(map[string]string{ "status": "ERROR", - "message": fmt.Sprintf("CloudEvent missing resource pool data"), + "message": "CloudEvent missing resource pool data", }) return } @@ -151,7 +151,7 @@ func (h *Handler) VmMoveEvent(w http.ResponseWriter, r *http.Request) { //fmt.Fprintf(w, "Processed update event: %v\n", result) json.NewEncoder(w).Encode(map[string]string{ "status": "OK", - "message": fmt.Sprintf("Successfully processed move event"), + "message": "Successfully processed move event", }) return } diff --git a/sqlc.yml b/sqlc.yml index 53f961a..d7b570b 100644 --- a/sqlc.yml +++ b/sqlc.yml @@ -1,11 +1,13 @@ version: 2 sql: - engine: sqlite - queries: - - db/queries/query.sql schema: - db/schema.sql + queries: + - db/queries/query.sql gen: go: package: queries out: db/queries + emit_json_tags: true + emit_db_tags: true diff --git a/src/postinstall.sh b/src/postinstall.sh new file mode 100644 index 0000000..4b89ac8 --- /dev/null +++ b/src/postinstall.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload || : + if [ "$1" -eq 1 ]; then + systemctl enable --now vctp.service || : + else + systemctl try-restart vctp.service || : + fi +fi diff --git a/src/postremove.sh b/src/postremove.sh new file mode 100644 index 0000000..d659822 --- /dev/null +++ b/src/postremove.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload || : + if [ "$1" -ge 1 ]; then + systemctl try-restart vctp.service || : + fi +fi diff --git a/src/preinstall.sh b/src/preinstall.sh new file mode 100644 index 0000000..6530410 --- /dev/null +++ b/src/preinstall.sh @@ -0,0 +1,45 @@ +#!/bin/bash +USER="vctp" +GROUP="dtms" + +# Path to the custom sudoers file +SUDOERS_FILE="/etc/sudoers.d/${USER}" + +# create a group & user if not exists +getent group "$GROUP" >/dev/null || groupadd -r "$GROUP"; /bin/true +getent passwd "$USER" >/dev/null || useradd -r -g "$GROUP" -m -s /bin/bash -c "vctp service" "$USER" +getent passwd tftp >/dev/null || useradd -r -g tftp -s /sbin/nologin tftp + +# create vctp config directory if it doesn't exist +[ -d /etc/dtms ] || mkdir -p /etc/dtms + +# set group ownership on vctp config directory if not already done +[ "$(stat -c "%G" /etc/dtms)" = "$GROUP" ] || chgrp -R "$GROUP" /etc/dtms + +# set permissions on vctp config directory if not already done +[ "$(stat -c "%a" /etc/dtms)" = "774" ] || chmod -R 774 /etc/dtms + +# create vctp data directory if it doesn't exist +[ -d /var/lib/vctp ] || mkdir -p /var/lib/vctp + +# set user ownership on vctp data directory if not already done +[ "$(stat -c "%U" /var/lib/vctp)" = "$USER" ] || chown -R "$USER" /var/lib/vctp + +# set group ownership on vctp data directory if not already done +[ "$(stat -c "%G" /var/lib/vctp)" = "$GROUP" ] || chgrp -R "$GROUP" /var/lib/vctp + +# Check if firewalld is installed and active +if command -v systemctl >/dev/null 2>&1 && systemctl is-enabled firewalld >/dev/null 2>&1 && systemctl is-active firewalld >/dev/null 2>&1; then + echo "Firewalld is enabled and running. Adding necessary ports..." + + # Open HTTPS port (443/tcp) + firewall-cmd --permanent --add-service=https >/dev/null 2>&1 + + # Open custom application port (9443/tcp) + firewall-cmd --permanent --add-port=9443/tcp >/dev/null 2>&1 + + # Reload firewalld to apply changes + firewall-cmd --reload >/dev/null 2>&1 +else + echo "Firewalld is not running or not enabled. Skipping firewall configuration." +fi diff --git a/src/preremove.sh b/src/preremove.sh new file mode 100644 index 0000000..9e1e8b3 --- /dev/null +++ b/src/preremove.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +if command -v systemctl >/dev/null 2>&1; then + if [ "$1" -eq 0 ]; then + systemctl stop vctp.service || : + systemctl disable vctp.service || : + fi +fi diff --git a/src/vctp.default b/src/vctp.default new file mode 100644 index 0000000..633406a --- /dev/null +++ b/src/vctp.default @@ -0,0 +1 @@ +CPE_OPTS='-config /etc/dtms/vctp.yml -log-level info -log-output text' diff --git a/src/vctp.service b/src/vctp.service new file mode 100644 index 0000000..eb81cd7 --- /dev/null +++ b/src/vctp.service @@ -0,0 +1,21 @@ +[Unit] +Description=vCTP monitors VMware VM inventory and event data to build chargeback reports +Documentation=https://gitlab.dell.com/ +ConditionPathExists=/usr/bin/vctp-linux-amd64 +After=network.target + +[Service] +Type=simple +EnvironmentFile=/etc/default/vctp +User=vctp +ExecStart=/usr/bin/vctp-linux-amd64 $CPE_OPTS +ExecStartPost=/usr/bin/sleep 3 +Restart=always +RestartSec=10s +#LimitNOFILE=65536 +SyslogIdentifier=vctp +#CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_FOWNER CAP_DAC_OVERRIDE CAP_SETUID CAP_SETGID CAP_SYS_RESOURCE CAP_AUDIT_WRITE +#AmbientCapabilities=CAP_NET_BIND_SERVICE + +[Install] +WantedBy=multi-user.target diff --git a/src/vctp.yml b/src/vctp.yml new file mode 100644 index 0000000..b6ac154 --- /dev/null +++ b/src/vctp.yml @@ -0,0 +1,25 @@ +settings: + data_location: "/var/lib/cbs" + kickstart_location: "/var/lib/cbs/ks" + database_filename: "/var/lib/cbs/cbs.db" + bind_ip: + bind_port: 443 + bind_disable_tls: false + tls_cert_filename: "/etc/dtms/cbs.crt" + tls_key_filename: "/etc/dtms/cbs.key" + tftp_root_directory: "/var/lib/tftpboot" + tftp_images_subdirectory: "images" + replacements: + omapi: + key_name: "OMAPI" + key_secret: + special_files: + ldap_groups: + ldap_bind_address: "" + ldap_base_dn: "" + ldap_trust_cert_file: "" + ldap_disable_validation: false + ldap_insecure: false + auth_token_lifespan_hours: 2 + auth_api_key: "" + \ No newline at end of file diff --git a/vctp.yml b/vctp.yml new file mode 100644 index 0000000..39acef0 --- /dev/null +++ b/vctp.yml @@ -0,0 +1,40 @@ +name: "vctp" +arch: "amd64" +platform: "linux" +version: "v26.1.1" +version_schema: semver +description: vCTP monitors VMware VM inventory and event data to build chargeback reports +maintainer: "@coadn" +vendor: "Dell Technologies Managed Services" +homepage: "https://gitlab.dell.com/" +license: "Apache-2.0" + +contents: + - src: build/vctp-linux-amd64 + dst: /usr/bin/vctp-linux-amd64 + + - src: src/vctp.yml + dst: /etc/dtms/vctp.yml + type: config|noreplace + file_info: + mode: 0644 + owner: vctp + group: dtms + + - src: src/vctp.service + dst: /usr/lib/systemd/system/vctp.service + + - src: src/vctp.default + dst: /etc/default/vctp + type: config|noreplace + +scripts: + preinstall: src/preinstall.sh + postinstall: src/postinstall.sh + preremove: src/preremove.sh + postremove: src/postremove.sh + +depends: + - systemd + - tftp-server + - dhcp-server