internal/status/status_windows.go (75 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package status import ( "encoding/json" "fmt" "github.com/Azure/azure-extension-foundation/errorhelper" "github.com/Azure/azure-extension-foundation/internal/settings" "io/ioutil" "os" "path/filepath" "time" ) type statusReport []statusItem type statusItem struct { Version float64 `json:"version"` TimestampUTC string `json:"timestampUTC"` Status status `json:"status"` } type status struct { Operation string `json:"operation"` Status string `json:"status"` FormattedMessage formattedMessage `json:"formattedMessage"` } type formattedMessage struct { Lang string `json:"lang"` Message string `json:"message"` } // ReportStatus saves operation status to the status file for the extension // handler with the optional given message, if the given cmd requires reporting // status. // // If an error occurs reporting the status, it will be logged and returned. func ReportStatus(sequenceNumber int, t string, operation, message string) error { s := newStatus(t, operation, message) hEnv, err := settings.GetEnvironment() if err != nil { return errorhelper.AddStackToError(fmt.Errorf("unable to get handler environment settings : %v", err)) } if err := s.Save(hEnv.HandlerEnvironment.StatusFolder, sequenceNumber); err != nil { //ctx.Log("event", "failed to save handler status", "error", err) return errorhelper.AddStackToError(fmt.Errorf("failed to save handler operation status : %s", err)) } return nil } // Save persists the status message to the specified status folder using the // sequence number. The operation consists of writing to a temporary file in the // same folder and moving it to the final destination for atomicity. func (r statusReport) Save(statusFolder string, seqNum int) error { fn := fmt.Sprintf("%d.status", seqNum) path := filepath.Join(statusFolder, fn) tmpFile, err := ioutil.TempFile(statusFolder, fn) if err != nil { return errorhelper.AddStackToError(fmt.Errorf("status: failed to create temporary file: %v", err)) } tmpFile.Close() b, err := r.marshal() if err != nil { return errorhelper.AddStackToError(fmt.Errorf("status: failed to marshal into json: %v", err)) } if err := ioutil.WriteFile(tmpFile.Name(), b, 0644); err != nil { return errorhelper.AddStackToError(fmt.Errorf("status: failed to path=%s error=%v", tmpFile.Name(), err)) } if err := os.Rename(tmpFile.Name(), path); err != nil { return errorhelper.AddStackToError(fmt.Errorf("status: failed to move to path=%s error=%v", path, err)) } return nil } func newStatus(t string, operation, message string) statusReport { return []statusItem{ { Version: 1.0, TimestampUTC: time.Now().UTC().Format(time.RFC3339), Status: status{ Operation: operation, Status: t, FormattedMessage: formattedMessage{ Lang: "en", Message: message}, }, }, } } func (r statusReport) marshal() ([]byte, error) { return json.MarshalIndent(r, "", "\t") }