diff --git a/.drone.sh b/.drone.sh old mode 100644 new mode 100755 diff --git a/.drone.yml b/.drone.yml index 0b6b8bb..1476f8f 100644 --- a/.drone.yml +++ b/.drone.yml @@ -16,6 +16,7 @@ steps: #- cp /shared/index.html ./www/ - go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest - sqlc generate + - chmod +x .drone.sh - ./.drone.sh - name: dell-sftp-deploy diff --git a/go.mod b/go.mod index 5d5675d..99ae867 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/pressly/goose/v3 v3.22.0 github.com/stretchr/testify v1.9.0 github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d + github.com/vmware/govmomi v0.43.0 modernc.org/sqlite v1.33.0 ) @@ -23,7 +24,6 @@ require ( github.com/go-stack/stack v1.8.1 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect - github.com/kr/text v0.2.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mfridman/interpolate v0.0.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect diff --git a/go.sum b/go.sum index 7b3a974..cd55cf4 100644 --- a/go.sum +++ b/go.sum @@ -6,7 +6,6 @@ github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYW github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo= github.com/coder/websocket v1.8.12/go.mod h1:LNVeNrXQZfe5qhS9ALED3uA+l5pPqvwXg3CKoDBB2gs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -67,6 +66,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d h1:dOMI4+zEbDI37KGb0TI44GUAwxHF9cMsIoDTJ7UmgfU= github.com/tursodatabase/libsql-client-go v0.0.0-20240902231107-85af5b9d094d/go.mod h1:l8xTsYB90uaVdMHXMCxKKLSgw5wLYBwBKKefNIUnm9s= +github.com/vmware/govmomi v0.43.0 h1:7Kg3Bkdly+TrE67BYXzRq7ZrDnn7xqpKX95uEh2f9Go= +github.com/vmware/govmomi v0.43.0/go.mod h1:IOv5nTXCPqH9qVJAlRuAGffogaLsNs8aF+e7vLgsHJU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/internal/vcenter/vcenter.go b/internal/vcenter/vcenter.go new file mode 100644 index 0000000..c50ff99 --- /dev/null +++ b/internal/vcenter/vcenter.go @@ -0,0 +1,106 @@ +package vcenter + +import ( + "context" + "fmt" + "log" + "log/slog" + "net/url" + "os" + + "github.com/vmware/govmomi" + "github.com/vmware/govmomi/view" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" +) + +type Vcenter struct { + logger *slog.Logger + ctx context.Context + client *govmomi.Client +} + +// New creates a new Vcenter with the given logger +func New(logger *slog.Logger) *Vcenter { + + //ctx, cancel := context.WithCancel(context.Background()) + //defer cancel() + + return &Vcenter{ + logger: logger, + ctx: context.Background(), + } +} + +func (v *Vcenter) Login(vUrl string) error { + var insecure bool + + insecureString := os.Getenv("VCENTER_INSECURE") + username := os.Getenv("VCENTER_USERNAME") + password := os.Getenv("VCENTER_PASSWORD") + + // Connect to vCenter + u, err := soap.ParseURL(vUrl) + if err != nil { + log.Fatalf("Error parsing vCenter URL: %s", err) + } + + u.User = url.UserPassword(username, password) + + /* + c, err := govmomi.NewClient(ctx, u, insecure) + if err != nil { + log.Fatalf("Error connecting to vCenter: %s", err) + } + */ + + if insecureString == "true" { + insecure = true + } + + c, err := govmomi.NewClient(v.ctx, u, insecure) + if err != nil { + v.logger.Error("Unable to connect to vCenter", "error", err) + return fmt.Errorf("unable to connect to vCenter : %s", err) + } + + //defer c.Logout(v.ctx) + + v.client = c + + return nil +} + +func (v *Vcenter) Logout() error { + return v.client.Logout(v.ctx) +} + +func (v *Vcenter) FindVMByName(vmName string) ([]mo.VirtualMachine, error) { + m := view.NewManager(v.client.Client) + + vms, err := m.CreateContainerView(v.ctx, v.client.ServiceContent.RootFolder, []string{"VirtualMachine"}, true) + if err != nil { + return nil, err + } + defer vms.Destroy(v.ctx) + + var matchingVMs []mo.VirtualMachine + + err = vms.Retrieve(v.ctx, []string{"VirtualMachine"}, []string{"name"}, &matchingVMs) + if err != nil { + return nil, err + } + + // Temporarily just return all VMs + //return matchingVMs, nil + + var result []mo.VirtualMachine + + for _, vm := range matchingVMs { + if vm.Name == vmName { + result = append(result, vm) + } + } + + return result, nil +} diff --git a/server/handler/vmCreate.go b/server/handler/vmCreate.go index 2292324..5b0d1e4 100644 --- a/server/handler/vmCreate.go +++ b/server/handler/vmCreate.go @@ -9,6 +9,7 @@ import ( "net/http" "time" queries "vctp/db/queries" + "vctp/internal/vcenter" models "vctp/server/models" ) @@ -27,7 +28,6 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) { // Decode the JSON body into vmModel struct var vm models.CloudEventReceived - //if err := json.NewDecoder(r.Body).Decode(&vm); err != nil { if err := json.Unmarshal(reqBody, &vm); err != nil { h.Logger.Error("unable to decode json", "error", err) http.Error(w, "Invalid JSON body", http.StatusBadRequest) @@ -48,6 +48,17 @@ func (h *Handler) VmCreate(w http.ResponseWriter, r *http.Request) { unixTimestamp = eventTime.Unix() } + // TODO - initiate govmomi query of source vcenter to discover related data + vc := vcenter.New(h.Logger) + vc.Login(vm.CloudEvent.Source) + vmObject, err := vc.FindVMByName(vm.CloudEvent.Data.VM.Name) + if err != nil { + h.Logger.Error("Can't locate vm in vCenter", "vmName", vm.CloudEvent.Data.VM.Name, "error", err) + } else { + h.Logger.Debug("found VM", "object", vmObject) + } + vc.Logout() + // Create an instance of CreateInventoryParams params := queries.CreateInventoryParams{ Name: vm.CloudEvent.Data.VM.Name,