github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/fly/commands/internal/setpipelinehelpers/atc_config.go (about)

     1  package setpipelinehelpers
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"sigs.k8s.io/yaml"
    11  
    12  	"github.com/vito/go-interact/interact"
    13  
    14  	"github.com/pf-qiu/concourse/v6/atc"
    15  	"github.com/pf-qiu/concourse/v6/atc/configvalidate"
    16  	"github.com/pf-qiu/concourse/v6/fly/commands/internal/displayhelpers"
    17  	"github.com/pf-qiu/concourse/v6/fly/commands/internal/templatehelpers"
    18  	"github.com/pf-qiu/concourse/v6/fly/rc"
    19  	"github.com/pf-qiu/concourse/v6/fly/ui"
    20  	"github.com/pf-qiu/concourse/v6/go-concourse/concourse"
    21  )
    22  
    23  type ATCConfig struct {
    24  	PipelineRef      atc.PipelineRef
    25  	Team             concourse.Team
    26  	TargetName       rc.TargetName
    27  	Target           string
    28  	SkipInteraction  bool
    29  	CheckCredentials bool
    30  	CommandWarnings  []concourse.ConfigWarning
    31  }
    32  
    33  func (atcConfig ATCConfig) ApplyConfigInteraction() bool {
    34  	if atcConfig.SkipInteraction {
    35  		return true
    36  	}
    37  
    38  	confirm := false
    39  	err := interact.NewInteraction("apply configuration?").Resolve(&confirm)
    40  	if err != nil {
    41  		return false
    42  	}
    43  
    44  	return confirm
    45  }
    46  
    47  func (atcConfig ATCConfig) Set(yamlTemplateWithParams templatehelpers.YamlTemplateWithParams) error {
    48  	evaluatedTemplate, err := yamlTemplateWithParams.Evaluate(false, false)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	existingConfig, existingConfigVersion, _, err := atcConfig.Team.PipelineConfig(atcConfig.PipelineRef)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	var newConfig atc.Config
    59  	err = yaml.Unmarshal([]byte(evaluatedTemplate), &newConfig)
    60  	if err != nil {
    61  		return err
    62  	}
    63  
    64  	configWarnings, _ := configvalidate.Validate(newConfig)
    65  	for _, w := range configWarnings {
    66  		atcConfig.CommandWarnings = append(atcConfig.CommandWarnings, concourse.ConfigWarning{
    67  			Type:    w.Type,
    68  			Message: w.Message,
    69  		})
    70  	}
    71  
    72  	diffExists := diff(existingConfig, newConfig)
    73  
    74  	if len(atcConfig.CommandWarnings) > 0 {
    75  		displayhelpers.ShowWarnings(atcConfig.CommandWarnings)
    76  	}
    77  
    78  	if !diffExists {
    79  		fmt.Println("no changes to apply")
    80  		return nil
    81  	}
    82  
    83  	fmt.Println(bold("pipeline name: ") + atcConfig.PipelineRef.Name)
    84  	if len(atcConfig.PipelineRef.InstanceVars) != 0 {
    85  		fmt.Println(bold("pipeline instance vars:"))
    86  		instanceVarsBytes, err := yaml.Marshal(atcConfig.PipelineRef.InstanceVars)
    87  		if err != nil {
    88  			return err
    89  		}
    90  		fmt.Println(indent(string(instanceVarsBytes), "  "))
    91  	}
    92  	fmt.Println()
    93  
    94  	if !atcConfig.ApplyConfigInteraction() {
    95  		fmt.Println("bailing out")
    96  		return nil
    97  	}
    98  
    99  	created, updated, warnings, err := atcConfig.Team.CreateOrUpdatePipelineConfig(
   100  		atcConfig.PipelineRef,
   101  		existingConfigVersion,
   102  		evaluatedTemplate,
   103  		atcConfig.CheckCredentials,
   104  	)
   105  	if err != nil {
   106  		return err
   107  	}
   108  
   109  	updatedConfig, found, err := atcConfig.Team.Pipeline(atcConfig.PipelineRef)
   110  	if err != nil {
   111  		return err
   112  	}
   113  
   114  	paused := found && updatedConfig.Paused
   115  
   116  	if len(warnings) > 0 {
   117  		displayhelpers.ShowWarnings(warnings)
   118  	}
   119  
   120  	atcConfig.showPipelineUpdateResult(created, updated, paused)
   121  	return nil
   122  }
   123  
   124  func (atcConfig ATCConfig) UnpausePipelineCommand() string {
   125  	pipelineFlag := atcConfig.PipelineRef.String()
   126  	if strings.Contains(pipelineFlag, `"`) {
   127  		pipelineFlag = strconv.Quote(pipelineFlag)
   128  	}
   129  	return fmt.Sprintf("%s -t %s unpause-pipeline -p %s", os.Args[0], atcConfig.TargetName, pipelineFlag)
   130  }
   131  
   132  func (atcConfig ATCConfig) showPipelineUpdateResult(created bool, updated bool, paused bool) {
   133  	if updated {
   134  		fmt.Println("configuration updated")
   135  	} else if created {
   136  
   137  		targetURL, err := url.Parse(atcConfig.Target)
   138  		if err != nil {
   139  			fmt.Println("Could not parse targetURL")
   140  		}
   141  
   142  		queryParams := atcConfig.PipelineRef.QueryParams().Encode()
   143  		if queryParams != "" {
   144  			queryParams = "?" + queryParams
   145  		}
   146  		pipelineURL, err := url.Parse("/teams/" + atcConfig.Team.Name() + "/pipelines/" + atcConfig.PipelineRef.Name + queryParams)
   147  		if err != nil {
   148  			fmt.Println("Could not parse pipelineURL")
   149  		}
   150  
   151  		fmt.Println("pipeline created!")
   152  		fmt.Printf("you can view your pipeline here: %s\n", targetURL.ResolveReference(pipelineURL))
   153  	} else {
   154  		panic("Something really went wrong!")
   155  	}
   156  
   157  	if paused {
   158  		fmt.Println("")
   159  		fmt.Println("the pipeline is currently paused. to unpause, either:")
   160  		fmt.Println("  - run the unpause-pipeline command:")
   161  		fmt.Println("    " + atcConfig.UnpausePipelineCommand())
   162  		fmt.Println("  - click play next to the pipeline in the web ui")
   163  	}
   164  }
   165  
   166  func diff(existingConfig atc.Config, newConfig atc.Config) bool {
   167  	stdout, _ := ui.ForTTY(os.Stdout)
   168  	return existingConfig.Diff(stdout, newConfig)
   169  }
   170  
   171  func indent(text, indent string) string {
   172  	text = strings.TrimRight(text, "\n")
   173  	var result strings.Builder
   174  	for _, line := range strings.Split(text, "\n") {
   175  		result.WriteString(indent + line + "\n")
   176  	}
   177  	return result.String()[:result.Len()-1]
   178  }
   179  
   180  func bold(text string) string {
   181  	return "\033[1m" + text + "\033[0m"
   182  }