github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/schema/v1beta9/upgrade.go (about) 1 /* 2 Copyright 2019 The Skaffold Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1beta9 18 19 import ( 20 "context" 21 "regexp" 22 "strings" 23 24 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log" 25 "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/util" 26 next "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/v1beta10" 27 pkgutil "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" 28 ) 29 30 const ( 31 incompatibleSyncWarning = `The semantics of sync has changed, the folder structure is no longer flattened but preserved (see https://skaffold.dev/docs/how-tos/filesync/). The likely impacted patterns in your skaffold yaml are: %s` 32 ) 33 34 var ( 35 // compatibleSimplePattern have a directory prefix without stars and a basename with at most one star. 36 compatibleSimplePattern = regexp.MustCompile(`^([^*]*/)?([^*/]*\*[^*/]*|[^*/]+)$`) 37 ) 38 39 // Upgrade upgrades a configuration to the next version. 40 // Config changes from v1beta9 to v1beta10 41 // 1. Additions: 42 // - DockerArtifact.NetworkMode 43 // 44 // 2. No removals 45 // 3. Updates: 46 // - sync map becomes a list of sync rules 47 func (c *SkaffoldConfig) Upgrade() (util.VersionedConfig, error) { 48 var newConfig next.SkaffoldConfig 49 pkgutil.CloneThroughJSON(c, &newConfig) 50 newConfig.APIVersion = next.Version 51 52 err := util.UpgradePipelines(c, &newConfig, upgradeOnePipeline) 53 return &newConfig, err 54 } 55 56 func upgradeOnePipeline(oldPipeline, newPipeline interface{}) error { 57 oldBuild := &oldPipeline.(*Pipeline).Build 58 newBuild := &newPipeline.(*next.Pipeline).Build 59 60 // set Sync in newBuild 61 newSyncRules := convertSyncRules(oldBuild.Artifacts) 62 for i, a := range newBuild.Artifacts { 63 if len(newSyncRules[i]) > 0 { 64 a.Sync = &next.Sync{ 65 Manual: newSyncRules[i], 66 } 67 } 68 } 69 return nil 70 } 71 72 // convertSyncRules converts the old sync map into sync rules. 73 // It also prints a warning message when some rules can not be upgraded. 74 func convertSyncRules(artifacts []*Artifact) [][]*next.SyncRule { 75 var incompatiblePatterns []string 76 newSync := make([][]*next.SyncRule, len(artifacts)) 77 for i, a := range artifacts { 78 newRules := make([]*next.SyncRule, 0, len(a.Sync)) 79 for src, dest := range a.Sync { 80 var syncRule *next.SyncRule 81 switch { 82 case compatibleSimplePattern.MatchString(src): 83 dest, strip := simplify(dest, compatibleSimplePattern.FindStringSubmatch(src)[1]) 84 syncRule = &next.SyncRule{ 85 Src: src, 86 Dest: dest, 87 Strip: strip, 88 } 89 case strings.Contains(src, "***"): 90 dest, strip := simplify(dest, strings.Split(src, "***")[0]) 91 syncRule = &next.SyncRule{ 92 Src: strings.ReplaceAll(src, "***", "**"), 93 Dest: dest, 94 Strip: strip, 95 } 96 default: 97 // Incompatible patterns contain `**` or glob directories. 98 // Such patterns flatten the content at the destination which 99 // cannot be reproduced with the current config. For example: 100 // `/app/**/subdir/*.html`, `/app/*/*.html` 101 incompatiblePatterns = append(incompatiblePatterns, src) 102 syncRule = &next.SyncRule{ 103 Src: src, 104 Dest: dest, 105 } 106 } 107 newRules = append(newRules, syncRule) 108 } 109 newSync[i] = newRules 110 // blank input sync because it breaks cloning 111 a.Sync = nil 112 } 113 if len(incompatiblePatterns) > 0 { 114 log.Entry(context.TODO()).Warnf(incompatibleSyncWarning, incompatiblePatterns) 115 } 116 return newSync 117 } 118 119 // simplify dest and strip, if strip is a suffix of dest modulo a trailing `/`. 120 func simplify(dest, strip string) (string, string) { 121 if strip == "" || strip == "/" || dest == "" { 122 return dest, strip 123 } 124 125 simpleStrip := strip 126 simpleDest := dest 127 128 if dest[len(dest)-1] != '/' { 129 dest += "/" 130 } 131 132 if strings.HasSuffix(dest, strip) { 133 simpleDest = strings.TrimSuffix(dest, strings.TrimPrefix(strip, "/")) 134 simpleStrip = "" 135 if simpleDest == "" { 136 simpleDest = "." 137 } 138 } 139 140 return simpleDest, simpleStrip 141 }