internal/engine/environments/azure.go (144 lines of code) (raw):

package environments import ( "encoding/json" "fmt" "strings" "github.com/Azure/InnovationEngine/internal/az" "github.com/Azure/InnovationEngine/internal/logging" "github.com/Azure/InnovationEngine/internal/patterns" "github.com/Azure/InnovationEngine/internal/ui" ) // codeblock metadata needed for learn mode deployments. type AzureCodeBlock struct { Description string `json:"description"` Command string `json:"command"` } // Step metadata needed for learn mode deployments. type AzureStep struct { Name string `json:"name"` CodeBlocks []AzureCodeBlock `json:"codeblocks"` } // The status of a one-click deployment or learn mode deployment. type AzureDeploymentStatus struct { Steps []AzureStep `json:"steps"` CurrentStep int `json:"currentStep"` Status string `json:"status"` ResourceURIs []string `json:"resourceURIs"` Error string `json:"error"` Output string `json:"output"` ConfiguredMarkdown string `json:"configuredMarkdown"` } func NewAzureDeploymentStatus() AzureDeploymentStatus { return AzureDeploymentStatus{ Steps: []AzureStep{}, CurrentStep: 0, Status: "Executing", ResourceURIs: []string{}, Error: "", ConfiguredMarkdown: "", Output: "", } } // Get the status as a JSON string. func (status *AzureDeploymentStatus) AsJsonString() (string, error) { json, err := json.Marshal(status) if err != nil { logging.GlobalLogger.Error("Failed to marshal status", err) return "", err } return string(json), nil } func (status *AzureDeploymentStatus) AddStep(step string, codeBlocks []AzureCodeBlock) { status.Steps = append(status.Steps, AzureStep{ Name: step, CodeBlocks: codeBlocks, }) } func (status *AzureDeploymentStatus) AddResourceURI(uri string) { status.ResourceURIs = append(status.ResourceURIs, uri) } func (status *AzureDeploymentStatus) SetError(err error) { status.Status = "Failed" status.Error = err.Error() } func (status *AzureDeploymentStatus) SetOutput(output string) { status.Output = output } // Given a markdown string, replace the environment variables with the values // provided in the environmentVariables map. Currently this is only used // by the portal. func (status *AzureDeploymentStatus) ConfigureMarkdownForDownload( markdown string, environmentVariables map[string]string, environment string, ) { if !IsAzureEnvironment(environment) { return } for key, value := range environmentVariables { exportRegex := patterns.ExportVariableRegex(key) matches := exportRegex.FindAllStringSubmatch(markdown, -1) if len(matches) != 0 { logging.GlobalLogger.Debugf( "Found %d matches for the environment variable %s, Replacing them in markdown source.", len(matches), key, ) } for _, match := range matches { oldLine := match[0] oldValue := match[1] // Replace the old export with the new export statement newLine := strings.Replace(oldLine, oldValue, value+" ", 1) logging.GlobalLogger.Debugf("Replacing '%s' with '%s'", oldLine, newLine) // Update the code block with the new export statement markdown = strings.Replace( markdown, oldLine, newLine, 1, ) } } status.ConfiguredMarkdown = markdown } // Print out the status JSON for azure/cloudshell if in the correct environment. func ReportAzureStatus(status AzureDeploymentStatus, environment string) { if !IsAzureEnvironment(environment) { return } statusJson, err := status.AsJsonString() if err != nil { logging.GlobalLogger.Error("Failed to marshal status", err) } else { // We add these strings to the output so that the portal can find and parse // the JSON status. ocdStatus := fmt.Sprintf("ie_us%sie_ue", statusJson) logging.GlobalLogger.Tracef("Generated status: %s", ocdStatus) fmt.Println(ui.OcdStatusUpdateStyle.Render(ocdStatus)) } } // Same as ReportAzureStatus, but returns the status string instead of printing it. func GetAzureStatus(status AzureDeploymentStatus, environment string) string { if !IsAzureEnvironment(environment) { return "" } statusJson, err := status.AsJsonString() if err != nil { logging.GlobalLogger.Error("Failed to marshal status", err) return "" } else { // We add these strings to the output so that the portal can find and parse // the JSON status. ocdStatus := fmt.Sprintf("ie_us%sie_ue", statusJson) return ocdStatus } } // Attach deployed resource URIs to the one click deployment status if we're in // the correct environment & we have a resource group name. func AttachResourceURIsToAzureStatus( status *AzureDeploymentStatus, resourceGroupName string, environment string, ) { if !IsAzureEnvironment(environment) { logging.GlobalLogger.Info( "Not fetching resource URIs because we're not in the OCD environment.", ) } if resourceGroupName == "" { logging.GlobalLogger.Warn("No resource group name found.") return } resourceURIs := az.FindAllDeployedResourceURIs(resourceGroupName) if len(resourceURIs) > 0 { logging.GlobalLogger.WithField("resourceURIs", resourceURIs). Info("Found deployed resources.") status.ResourceURIs = append(status.ResourceURIs, resourceURIs...) } else { logging.GlobalLogger.Warn("No deployed resources found.") } }