cmd/ops_agent_windows/main_windows.go (124 lines of code) (raw):
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"flag"
"fmt"
"log"
"os"
"path/filepath"
"github.com/GoogleCloudPlatform/ops-agent/internal/healthchecks"
"github.com/GoogleCloudPlatform/ops-agent/internal/logs"
"github.com/kardianos/osext"
"golang.org/x/sys/windows/svc"
)
const dataDirectory = `Google/Cloud Operations/Ops Agent`
const serviceName = "google-cloud-ops-agent"
const serviceDisplayName = "Google Cloud Ops Agent"
var (
installServices = flag.Bool("install", false, "whether to install the services")
uninstallServices = flag.Bool("uninstall", false, "whether to uninstall the services")
healthChecks = flag.Bool("healthchecks", false, "run health checks and exit")
)
func main() {
infoLog := logs.NewSimpleLogger()
if ok, err := svc.IsWindowsService(); ok && err == nil {
if err := run(serviceName); err != nil {
log.Fatal(err)
}
} else if err != nil {
log.Fatalf("failed to talk to service control manager: %v", err)
} else {
flag.Parse()
if *installServices && *uninstallServices {
log.Fatal("Can't use both --install and --uninstall")
}
if *installServices {
if err := install(); err != nil {
log.Fatal(err)
}
infoLog.Printf("installed services")
} else if *uninstallServices {
if err := uninstall(); err != nil {
log.Fatal(err)
}
infoLog.Printf("uninstalled services")
} else if *healthChecks {
healthCheckResults := getHealthCheckResults()
healthchecks.LogHealthCheckResults(healthCheckResults, infoLog)
infoLog.Println("Health checks finished")
} else {
// TODO: add an interactive GUI box with the Install, Uninstall, and Cancel buttons.
fmt.Println("Invoked as a standalone program with no flags. Nothing to do.")
fmt.Println("Use either --healthchecks, --install, --uninstall to take action.")
}
}
}
var services []struct {
name string
displayName string
exepath string
args []string
}
func init() {
if err := initServices(); err != nil {
log.Fatal(err)
}
}
func initServices() error {
// Identify relevant paths
self, err := osext.Executable()
if err != nil {
return fmt.Errorf("could not determine own path: %w", err)
}
base, err := osext.ExecutableFolder()
if err != nil {
return fmt.Errorf("could not determine binary path: %w", err)
}
configOutDir := filepath.Join(os.Getenv("PROGRAMDATA"), dataDirectory, "generated_configs")
if err := os.MkdirAll(configOutDir, 0644); err != nil {
return err
}
fluentbitStoragePath := filepath.Join(os.Getenv("PROGRAMDATA"), dataDirectory, `run\buffers`)
if err := os.MkdirAll(fluentbitStoragePath, 0644); err != nil {
return err
}
logDirectory := filepath.Join(os.Getenv("PROGRAMDATA"), dataDirectory, "log")
if err := os.MkdirAll(logDirectory, 0644); err != nil {
return err
}
// TODO: Write meaningful descriptions for these services
services = []struct {
name string
displayName string
exepath string
args []string
}{
{
serviceName,
serviceDisplayName,
self,
[]string{
"-in", filepath.Join(base, "../config/config.yaml"),
"-out", configOutDir,
},
},
{
fmt.Sprintf("%s-opentelemetry-collector", serviceName),
fmt.Sprintf("%s - Metrics Agent", serviceDisplayName),
filepath.Join(base, "google-cloud-metrics-agent_windows_amd64.exe"),
[]string{
"--config=" + filepath.Join(configOutDir, `otel\otel.yaml`),
},
},
{
// TODO: fluent-bit hardcodes a service name of "fluent-bit"; do we need to match that?
fmt.Sprintf("%s-fluent-bit", serviceName),
fmt.Sprintf("%s - Logging Agent", serviceDisplayName),
filepath.Join(base, fmt.Sprintf("%s-wrapper.exe", serviceName)),
[]string{
"-log_path", filepath.Join(logDirectory, "logging-module.log"),
"-config_path", filepath.Join(base, "../config/config.yaml"),
filepath.Join(base, "fluent-bit.exe"),
"-c", filepath.Join(configOutDir, `fluentbit\fluent_bit_main.conf`),
"-R", filepath.Join(configOutDir, `fluentbit\fluent_bit_parser.conf`),
"--storage_path", fluentbitStoragePath,
},
},
}
return nil
}