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 }