github.com/verrazzano/verrazzano@v1.7.1/tools/vz/pkg/internal/util/report/action.go (about)

     1  // Copyright (c) 2021, 2024, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  // Package report handles reporting
     5  package report
     6  
     7  import (
     8  	"errors"
     9  	"fmt"
    10  
    11  	"github.com/verrazzano/verrazzano/tools/vz/cmd/version"
    12  	"go.uber.org/zap"
    13  )
    14  
    15  // TODO: Add helpers for working with Actions
    16  
    17  // NOTE: This is part of the contract with the analyzers however it is currently an initial stake in the ground and
    18  //		 will be evolving rapidly initially as we add analysis cases
    19  
    20  // Action describes what a user/developer should do to mitigate an issue that has been found. For example:
    21  //   - Description of the action if more general
    22  //   - Link(s) to a Runbook(s) are preferable here as instructions may evolve over time and may be complex
    23  //   - A list of Steps to take
    24  type Action struct {
    25  	Summary string   // Required, Summary of the action to take
    26  	Links   []string // Optional, runbook or other related Links with action details
    27  	Steps   []string // Optional, list of Steps to take (pointing to runbook is preferable if Actions are complex)
    28  }
    29  
    30  // Validate validates the action
    31  func (action *Action) Validate(log *zap.SugaredLogger) (err error) {
    32  	if len(action.Summary) == 0 {
    33  		return errors.New("A Summary is required for an Action")
    34  	}
    35  	return nil
    36  }
    37  
    38  // Standard Action Summaries
    39  const (
    40  	ConsultRunbook = "Consult %s using supporting details identified in the report"
    41  )
    42  
    43  // RunbookLinks are known runbook links
    44  var RunbookLinks = map[string][]string{
    45  	ImagePullBackOff:             {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/imagepullbackoff"},
    46  	ImagePullRateLimit:           {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/imagepullratelimit"},
    47  	ImagePullNotFound:            {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/imagepullnotfound"},
    48  	ImagePullService:             {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/imagepullservice"},
    49  	InsufficientMemory:           {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/insufficientmemory"},
    50  	InsufficientCPU:              {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/insufficientcpu"},
    51  	IngressInstallFailure:        {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingressinstallfailure"},
    52  	IngressLBLimitExceeded:       {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingresslblimitexceeded"},
    53  	IngressNoLoadBalancerIP:      {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingressnoloadbalancerip"},
    54  	IngressOciIPLimitExceeded:    {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingressociiplimitexceeded"},
    55  	InstallFailure:               {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/installfailure"},
    56  	PendingPods:                  {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/pendingpods"},
    57  	PodProblemsNotReported:       {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/podproblemsnotreported"},
    58  	IngressNoIPFound:             {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingressnoloadbalancerip"},
    59  	IstioIngressNoIP:             {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/istioingressgatewaynoloadbalancerip"},
    60  	IngressShapeInvalid:          {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/ingressinvalidshape"},
    61  	IstioIngressPrivateSubnet:    {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/istioloadbalancercreation"},
    62  	NginxIngressPrivateSubnet:    {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/nginxloadbalancercreation"},
    63  	ExternalDNSConfigureIssue:    {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/externaldnsconfiguration"},
    64  	KeycloakDataMigrationFailure: {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/keycloakdatamigrationfailure"},
    65  	ClusterAPIClusterIssues:      {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/clusterapiclusterissues"},
    66  	RancherIssues:                {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/rancherissues"},
    67  	BlockStorageLimitExceeded:    {"https://verrazzano.io/" + version.GetEffectiveDocsVersion() + "/docs/troubleshooting/diagnostictools/analysisadvice/blockstoragelimitexceeded"},
    68  }
    69  
    70  // KnownActions are Standard Action types
    71  var KnownActions = map[string]Action{
    72  	ImagePullBackOff:             {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ImagePullBackOff][0])},
    73  	ImagePullRateLimit:           {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ImagePullRateLimit][0])},
    74  	ImagePullNotFound:            {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ImagePullNotFound][0])},
    75  	ImagePullService:             {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ImagePullService][0])},
    76  	InsufficientMemory:           {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[InsufficientMemory][0])},
    77  	InsufficientCPU:              {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[InsufficientCPU][0])},
    78  	IngressInstallFailure:        {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressInstallFailure][0])},
    79  	IngressLBLimitExceeded:       {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressLBLimitExceeded][0])},
    80  	IngressNoLoadBalancerIP:      {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressNoLoadBalancerIP][0])},
    81  	IngressOciIPLimitExceeded:    {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressOciIPLimitExceeded][0])},
    82  	InstallFailure:               {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[InstallFailure][0])},
    83  	PendingPods:                  {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[PendingPods][0])},
    84  	PodProblemsNotReported:       {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[PodProblemsNotReported][0])},
    85  	IngressNoIPFound:             {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressNoIPFound][0])},
    86  	IstioIngressNoIP:             {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IstioIngressNoIP][0])},
    87  	IngressShapeInvalid:          {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IngressShapeInvalid][0])},
    88  	IstioIngressPrivateSubnet:    {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[IstioIngressPrivateSubnet][0])},
    89  	NginxIngressPrivateSubnet:    {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[NginxIngressPrivateSubnet][0])},
    90  	ExternalDNSConfigureIssue:    {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ExternalDNSConfigureIssue][0])},
    91  	KeycloakDataMigrationFailure: {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[KeycloakDataMigrationFailure][0])},
    92  	ClusterAPIClusterIssues:      {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[ClusterAPIClusterIssues][0])},
    93  	RancherIssues:                {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[RancherIssues][0])},
    94  	BlockStorageLimitExceeded:    {Summary: getConsultRunbookAction(ConsultRunbook, RunbookLinks[BlockStorageLimitExceeded][0])},
    95  }
    96  
    97  func getConsultRunbookAction(summaryF string, runbookLink string) string {
    98  	return fmt.Sprintf(summaryF, runbookLink)
    99  }