extensionlauncher/extensionlauncher.go (70 lines of code) (raw):
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
package extensionlauncher
import (
"flag"
"fmt"
"github.com/Azure/azure-extension-platform/pkg/exithelper"
"github.com/Azure/azure-extension-platform/pkg/handlerenv"
"github.com/Azure/azure-extension-platform/pkg/logging"
"github.com/Azure/azure-extension-platform/pkg/seqno"
"github.com/Azure/azure-extension-platform/pkg/status"
"github.com/Azure/azure-extension-platform/pkg/utils"
"github.com/Azure/azure-extension-platform/vmextension"
"github.com/pkg/errors"
"os"
"path"
)
var eh = exithelper.Exiter
func Run(handlerEnv *handlerenv.HandlerEnvironment, el *logging.ExtensionLogger, extensionName, extensionVersion, exeName, operation string) {
writeTransitioningStatusAndStartExtensionAsASeparateProcess(extensionName, extensionVersion, exeName, operation, handlerEnv, el)
}
func ParseArgs() (extensionName, extensionVersion, exeName, operation string, err error) {
flag.StringVar(&extensionName, "extensionname", "", "name of the extension")
flag.StringVar(&extensionVersion, "extensionversion", "", "version of the extension")
flag.StringVar(&exeName, "exename", "", "the name of the extension executable file")
flag.StringVar(&operation, "operation", "", "the operation to perform on the extension")
flag.Parse()
if extensionName == "" {
err = fmt.Errorf("could not parse extension name")
}
if extensionVersion == "" {
err = errors.Wrap(err, "could not parse extension version")
}
if exeName == "" {
err = errors.Wrap(err, "could not parse extension executable name")
}
if operation == "" {
err = errors.Wrap(err, "could not parse operation")
}
return
}
func writeTransitioningStatusAndStartExtensionAsASeparateProcess(extensionName, extensionVersion, exeName, operation string, handlerEnv *handlerenv.HandlerEnvironment, el *logging.ExtensionLogger) {
writeTransitioningStatus(extensionName, extensionVersion, operation, handlerEnv, el)
workingDir, err := utils.GetCurrentProcessWorkingDir()
if err != nil {
el.Error("could not get current working directory %s", err.Error())
eh.Exit(exithelper.EnvironmentError)
}
runExecutableAsIndependentProcess(exeName, operation, workingDir, handlerEnv.LogFolder, el)
}
func writeTransitioningStatus(extensionName, extensionVersion, operation string, handlerEnv *handlerenv.HandlerEnvironment, el *logging.ExtensionLogger) {
if operation == vmextension.EnableOperation.ToString() {
// we write transitioning status only for Enable command
currentSequenceNumber, err := seqno.FindSeqNum(el, handlerEnv.ConfigFolder)
if err != nil {
el.Error("could not retrieve the current sequence number %s", err.Error())
eh.Exit(exithelper.EnvironmentError)
}
// if status file exists, no need to overwrite it
statusFilePath := path.Join(handlerEnv.StatusFolder, fmt.Sprintf("%d.status", currentSequenceNumber))
fileInfo, statErr := os.Stat(statusFilePath)
if os.IsNotExist(statErr) {
statusReport := status.New(status.StatusTransitioning, vmextension.EnableOperation.ToStatusName(), fmt.Sprintf("extension %s version %s started execution", extensionName, extensionVersion))
err := statusReport.Save(handlerEnv.StatusFolder, currentSequenceNumber)
if err != nil {
// don't exit
el.Warn("could not write transitioning status for extension %s version %s", extensionName, extensionVersion)
}
} else if fileInfo != nil {
el.Info("%d.status file already exists, will not create new status file with transitioning status", currentSequenceNumber)
} else if err != nil {
el.Warn("could not determine the existence or absence of status file, will continue without writing placeholder status file")
}
}
}