agent/inventory/gatherers/service/dataProvider.go (94 lines of code) (raw):
package service
import (
"encoding/json"
"fmt"
"github.com/aliyun/aliyun_assist_client/agent/log"
"github.com/aliyun/aliyun_assist_client/agent/util/stringutil"
"github.com/aliyun/aliyun_assist_client/common/executil"
"github.com/aliyun/aliyun_assist_client/agent/inventory/model"
"github.com/google/uuid"
)
var (
startMarker = "<start" + randomString(8) + ">"
endMarker = "<end" + randomString(8) + ">"
serviceInfoScript = `
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$serviceInfo = Get-Service | Select-Object Name, DisplayName, Status, DependentServices, ServicesDependedOn, ServiceType, StartType
$jsonObj = @()
foreach($s in $serviceInfo) {
$Name = $s.Name
$DisplayName = $s.DisplayName
$Status = $s.Status
$DependentServices = $s.DependentServices
$ServicesDependedOn = $s.ServicesDependedOn
$ServiceType = $s.ServiceType
$StartType = $s.StartType
$jsonObj += @"
{"Name": "` + mark(`$Name`) + `", "DisplayName": "` + mark(`$DisplayName`) + `", "Status": "$Status", "DependentServices": "` + mark(`$DependentServices`) + `",
"ServicesDependedOn": "` + mark(`$ServicesDependedOn`) + `", "ServiceType": "$ServiceType", "StartType": "$StartType"}
"@
}
$result = $jsonObj -join ","
$result = "[" + $result + "]"
[Console]::WriteLine($result)
`
)
const (
PowerShellCmd = "powershell"
)
func randomString(length int) string {
return uuid.New().String()[:length]
}
func mark(s string) string {
return startMarker + s + endMarker
}
var cmdExecutor = executeCommand
func executeCommand(command string, args ...string) ([]byte, error) {
return executil.Command(command, args...).CombinedOutput()
}
func executePowershellCommands(command, args string) (output []byte, err error) {
if output, err = cmdExecutor(PowerShellCmd, command+" "+args); err != nil {
log.GetLogger().Debugf("Failed to execute command: %v %v with error - %v",
command,
args,
err.Error())
log.GetLogger().Debugf("Command Stderr: %v", string(output))
err = fmt.Errorf("Command failed with error: %v", string(output))
}
return
}
func collectDataFromPowerShell(powershellCommand string, serviceInfo *[]model.ServiceData) (err error) {
var output []byte
var cleanOutPut string
log.GetLogger().Debugf("Executing command: %v", powershellCommand)
output, err = executePowershellCommands(powershellCommand, "")
if err != nil {
log.GetLogger().Errorf("Error executing command - %v", err.Error())
return
}
log.GetLogger().Debugf("Command output before clean up: %v", string(cleanOutPut))
cleanOutPut, err = stringutil.ReplaceMarkedFields(stringutil.CleanupNewLines(string(output)), startMarker, endMarker, stringutil.CleanupJSONField)
if err != nil {
log.GetLogger().Error(err)
}
log.GetLogger().Debugf("Command output: %v", string(cleanOutPut))
if err = json.Unmarshal([]byte(cleanOutPut), serviceInfo); err != nil {
err = fmt.Errorf("Unable to parse command output - %v", err.Error())
log.GetLogger().Errorf(err.Error())
log.GetLogger().Debugf("Error parsing command output - no data to return")
}
if serviceInfo != nil && len(*serviceInfo) > ServiceCountLimit {
err = fmt.Errorf(ServiceCountLimitExceeded+", got %d", len(*serviceInfo))
return
}
return
}
func collectServiceData(config model.Config) (data []model.ServiceData, err error) {
log.GetLogger().Debugf("collectServiceData called")
err = collectDataFromPowerShell(serviceInfoScript, &data)
if err != nil {
log.GetLogger().WithError(err).Error("collect service failed")
return []model.ServiceData{}, err
}
return
}