pkg/handlerenv/handlerenv.go (100 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package handlerenv import ( "encoding/json" "fmt" "github.com/Azure/azure-extension-platform/pkg/extensionerrors" "github.com/Azure/azure-extension-platform/pkg/utils" "io/ioutil" "os" "path/filepath" ) const handlerEnvFileName = "HandlerEnvironment.json" // HandlerEnvironment describes the handler environment configuration for an extension type HandlerEnvironment struct { HeartbeatFile string StatusFolder string ConfigFolder string LogFolder string DataFolder string EventsFolder string DeploymentID string RoleName string Instance string HostResolverAddress string } // HandlerEnvironment describes the handler environment configuration presented // to the extension handler by the Azure Guest Agent. type handlerEnvironmentInternal struct { Version float64 `json:"version"` Name string `json:"name"` HandlerEnvironment struct { HeartbeatFile string `json:"heartbeatFile"` StatusFolder string `json:"statusFolder"` ConfigFolder string `json:"configFolder"` LogFolder string `json:"logFolder"` EventsFolder string `json:"eventsFolder"` EventsFolderPreview string `json:"eventsFolder_preview"` DeploymentID string `json:"deploymentid"` RoleName string `json:"rolename"` Instance string `json:"instance"` HostResolverAddress string `json:"hostResolverAddress"` } } // GetHandlerEnv locates the HandlerEnvironment.json file by assuming it lives // next to or one level above the extension handler (read: this) executable, // reads, parses and returns it. func GetHandlerEnvironment(name, version string) (he *HandlerEnvironment, _ error) { contents, _, err := findAndReadFile(handlerEnvFileName) if err != nil { return nil, err } handlerEnvInternal, err := parseHandlerEnv(contents) if err != nil { return nil, err } // TODO: before this API goes public, remove the eventsfolder_preview // This is only used for private preview of the events eventsFolder := handlerEnvInternal.HandlerEnvironment.EventsFolder if eventsFolder == "" { eventsFolder = handlerEnvInternal.HandlerEnvironment.EventsFolderPreview } dataFolder := utils.GetDataFolder(name, version) return &HandlerEnvironment{ HeartbeatFile: handlerEnvInternal.HandlerEnvironment.HeartbeatFile, StatusFolder: handlerEnvInternal.HandlerEnvironment.StatusFolder, ConfigFolder: handlerEnvInternal.HandlerEnvironment.ConfigFolder, LogFolder: handlerEnvInternal.HandlerEnvironment.LogFolder, DataFolder: dataFolder, EventsFolder: eventsFolder, DeploymentID: handlerEnvInternal.HandlerEnvironment.DeploymentID, RoleName: handlerEnvInternal.HandlerEnvironment.RoleName, Instance: handlerEnvInternal.HandlerEnvironment.Instance, HostResolverAddress: handlerEnvInternal.HandlerEnvironment.HostResolverAddress, }, nil } // ParseHandlerEnv parses the HandlerEnvironment.json format. func parseHandlerEnv(b []byte) (*handlerEnvironmentInternal, error) { var hf []handlerEnvironmentInternal if err := json.Unmarshal(b, &hf); err != nil { return nil, fmt.Errorf("vmextension: failed to parse handler env: %v", err) } if len(hf) != 1 { return nil, fmt.Errorf("vmextension: expected 1 config in parsed HandlerEnvironment, found: %v", len(hf)) } return &hf[0], nil } // findAndReadFile locates the specified file on disk relative to our currently // executing process and attempts to read the file func findAndReadFile(fileName string) (b []byte, fileLoc string, _ error) { dir, err := utils.GetCurrentProcessWorkingDir() if err != nil { return nil, "", fmt.Errorf("vmextension: cannot find base directory of the running process: %v", err) } paths := []string{ filepath.Join(dir, fileName), // this level (i.e. executable is in [EXT_NAME]/.) filepath.Join(dir, "..", fileName), // one up (i.e. executable is in [EXT_NAME]/bin/.) } for _, p := range paths { o, err := ioutil.ReadFile(p) if err != nil && !os.IsNotExist(err) { return nil, "", fmt.Errorf("vmextension: error examining '%s' at '%s': %v", fileName, p, err) } else if err == nil { fileLoc = p b = o break } } if b == nil { return nil, "", extensionerrors.ErrNotFound } return b, fileLoc, nil }