Merge pull request #2 from Azure/dev/vivekl/fixGetSequenceNumber
Fix Get sequence number from config folder
This commit is contained in:
Коммит
63e98f8b38
38
main/cmds.go
38
main/cmds.go
|
@ -73,49 +73,11 @@ func install(ctx *log.Context, h HandlerEnvironment, report *RunCommandInstanceV
|
|||
return "", "", errors.Wrap(err, "failed to create data dir")
|
||||
}
|
||||
|
||||
// If the file mrseq does not exists
|
||||
// the extension has never been installed on this VMs before
|
||||
// if _, err := os.Stat(mostRecentSequence); os.IsNotExist(err) {
|
||||
// migrateToMostRecentSequence(ctx, h, seqNum)
|
||||
// }
|
||||
|
||||
ctx.Log("event", "created data dir", "path", dataDir)
|
||||
ctx.Log("event", "installed")
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
func migrateToMostRecentSequence(ctx *log.Context, h HandlerEnvironment, seqNum int) {
|
||||
// The status folder is used instead of the settings because the settings file is written
|
||||
// by the agent before install is called. As a result, the extension cannot determine if this
|
||||
// is a new install or an upgrade.
|
||||
//
|
||||
// If this is an upgrade there will be a status file. The agent will re-write the last status
|
||||
// file to indicate that the upgrade happened successfully. The extension uses the last status
|
||||
// sequence number to determine the last settings file that was executed.
|
||||
//
|
||||
// The agent helpfully copies mrseq every time an extension is upgraded thereby preserving the
|
||||
// most recent executed sequence. If extensions use mrseq they benefit from this mechanism, and
|
||||
// do not have invent another method. The CustomScript extension should have been using this
|
||||
// from the beginning, but it was not.
|
||||
//
|
||||
computedSeqNum, err := FindSeqNumStatus(h.HandlerEnvironment.StatusFolder)
|
||||
if err != nil {
|
||||
// If there was an error, the sequence number is zero.
|
||||
ctx.Log("event", "migrate to mrseq", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
fout, err := os.Create(mostRecentSequence)
|
||||
if err != nil {
|
||||
ctx.Log("event", "migrate to mrseq", "error", err)
|
||||
return
|
||||
}
|
||||
defer fout.Close()
|
||||
|
||||
ctx.Log("event", "migrate to mrseq", "message", fmt.Sprintf("migrated mrseq to %v", computedSeqNum))
|
||||
fout.WriteString(fmt.Sprintf("%v", computedSeqNum))
|
||||
}
|
||||
|
||||
func uninstall(ctx *log.Context, h HandlerEnvironment, report *RunCommandInstanceView, extName string, seqNum int) (string, string, error) {
|
||||
{ // a new context scope with path
|
||||
ctx = ctx.With("path", dataDir)
|
||||
|
|
|
@ -23,16 +23,6 @@ type handlerSettingsCommon struct {
|
|||
SettingsCertThumbprint string `json:"protectedSettingsCertThumbprint"`
|
||||
}
|
||||
|
||||
// settingsPath returns the full path to the .settings file with the
|
||||
// highest sequence number found in configFolder.
|
||||
func settingsPath(configFolder string) (string, error) {
|
||||
seq, err := FindSeqNumConfig(configFolder)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Cannot find seqnum: %v", err)
|
||||
}
|
||||
return filepath.Join(configFolder, fmt.Sprintf("%d%s", seq, ".settings")), nil
|
||||
}
|
||||
|
||||
// ReadSettings locates the .settings file and returns public settings
|
||||
// JSON, and protected settings JSON (by decrypting it with the keys in
|
||||
// configFolder).
|
||||
|
|
33
main/main.go
33
main/main.go
|
@ -37,6 +37,8 @@ var (
|
|||
|
||||
// configExtensionName environment variable should be set by VMAgent to extension name
|
||||
configExtensionName = "ConfigExtensionName"
|
||||
|
||||
configFileExtension = ".settings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -64,23 +66,26 @@ func main() {
|
|||
os.Exit(cmd.failExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
extensionName := os.Getenv(configExtensionName)
|
||||
if extensionName != "" {
|
||||
ctx = ctx.With("extensionName", extensionName)
|
||||
downloadDir = downloadDir + "/" + extensionName
|
||||
mostRecentSequence = extensionName + "." + mostRecentSequence
|
||||
pidFilePath = extensionName + "." + pidFilePath
|
||||
}
|
||||
|
||||
// Read the seqNum from latest config file in case VMAgent did not set it as env variable
|
||||
if seqNum == -1 {
|
||||
seqNum, err = FindSeqNumConfig(hEnv.HandlerEnvironment.ConfigFolder)
|
||||
seqNum, err = FindSequenceNumberFromConfig(hEnv.HandlerEnvironment.ConfigFolder, configFileExtension, extensionName)
|
||||
if err != nil {
|
||||
ctx.Log("messsage", "failed to find sequence number", "error", err)
|
||||
ctx.Log("FindSequenceNumberFromConfig", "failed to find sequence number from config folder.", "error", err)
|
||||
} else {
|
||||
ctx.Log("FindSequenceNumberFromConfig", fmt.Sprintf("Sequence number determined from config folder: %d", seqNum))
|
||||
}
|
||||
}
|
||||
ctx = ctx.With("seq", seqNum)
|
||||
|
||||
extName := os.Getenv(configExtensionName)
|
||||
if extName != "" {
|
||||
ctx = ctx.With("extensionName", extName)
|
||||
downloadDir = downloadDir + "/" + extName
|
||||
mostRecentSequence = extName + "." + mostRecentSequence
|
||||
pidFilePath = extName + "." + pidFilePath
|
||||
}
|
||||
|
||||
// check sub-command preconditions, if any, before executing
|
||||
ctx.Log("event", "start")
|
||||
if cmd.pre != nil {
|
||||
|
@ -100,15 +105,15 @@ func main() {
|
|||
EndTime: "",
|
||||
}
|
||||
|
||||
reportInstanceView(ctx, hEnv, extName, seqNum, StatusTransitioning, cmd, &instanceView)
|
||||
reportInstanceView(ctx, hEnv, extensionName, seqNum, StatusTransitioning, cmd, &instanceView)
|
||||
|
||||
// execute the subcommand
|
||||
stdout, stderr, err := cmd.invoke(ctx, hEnv, &instanceView, extName, seqNum)
|
||||
stdout, stderr, err := cmd.invoke(ctx, hEnv, &instanceView, extensionName, seqNum)
|
||||
if err != nil {
|
||||
ctx.Log("event", "failed to handle", "error", err)
|
||||
instanceView.ExecutionMessage = "Execution failed: " + err.Error()
|
||||
instanceView.EndTime = time.Now().UTC().Format(time.RFC3339)
|
||||
reportInstanceView(ctx, hEnv, extName, seqNum, StatusSuccess, cmd, &instanceView)
|
||||
reportInstanceView(ctx, hEnv, extensionName, seqNum, StatusSuccess, cmd, &instanceView)
|
||||
os.Exit(cmd.failExitCode)
|
||||
}
|
||||
instanceView.ExecutionMessage = "Execution completed"
|
||||
|
@ -116,7 +121,7 @@ func main() {
|
|||
instanceView.Output = stdout
|
||||
instanceView.Error = stderr
|
||||
instanceView.EndTime = time.Now().UTC().Format(time.RFC3339)
|
||||
reportInstanceView(ctx, hEnv, extName, seqNum, StatusSuccess, cmd, &instanceView)
|
||||
reportInstanceView(ctx, hEnv, extensionName, seqNum, StatusSuccess, cmd, &instanceView)
|
||||
ctx.Log("event", "end")
|
||||
}
|
||||
|
||||
|
|
|
@ -17,29 +17,22 @@ const (
|
|||
chmod = os.FileMode(0600)
|
||||
)
|
||||
|
||||
// FindSeqNumConfig gets the laster seq no from config files
|
||||
func FindSeqNumConfig(path string) (int, error) {
|
||||
return FindSeqNum(path, ".settings")
|
||||
}
|
||||
|
||||
// FindSeqNumStatus gets the laster seq no from status files
|
||||
func FindSeqNumStatus(path string) (int, error) {
|
||||
return FindSeqNum(path, ".status")
|
||||
}
|
||||
|
||||
// FindSeqNum finds the file with the highest number under configFolder
|
||||
// named like 0.settings, 1.settings so on.
|
||||
func FindSeqNum(path, ext string) (int, error) {
|
||||
g, err := filepath.Glob(filepath.Join(path, fmt.Sprintf("*%s", ext)))
|
||||
// FindSequenceNumberFromConfig finds the file with the highest sequence number for an extension under configFolder
|
||||
// named like <RunCommandName>.0.settings, <RunCommandName>.1.settings so on.
|
||||
func FindSequenceNumberFromConfig(path, fileExtension string, extensionName string) (int, error) {
|
||||
g, err := filepath.Glob(filepath.Join(path, fmt.Sprintf("%s.*%s", extensionName, fileExtension)))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
seqs := make([]int, len(g))
|
||||
for _, v := range g {
|
||||
f := filepath.Base(v)
|
||||
i, err := strconv.Atoi(strings.TrimSuffix(f, filepath.Ext(f)))
|
||||
fileNameWithoutExtension := strings.TrimSuffix(f, filepath.Ext(f))
|
||||
dotAndSequenceNumberString := filepath.Ext(fileNameWithoutExtension) // returns something like ".<sequenceNumber>"
|
||||
sequenceNumberString := dotAndSequenceNumberString[1:] // Remove '.' in the front
|
||||
i, err := strconv.Atoi(sequenceNumberString)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("Can't parse int from filename: %s", f)
|
||||
continue // continue to the next filename if Atoi fails
|
||||
}
|
||||
seqs = append(seqs, i)
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче