This is an automated email from the ASF dual-hosted git repository. neuman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push: new d74de45 Add ORT/atstccfg Deterministic Config Generation (#4557) d74de45 is described below commit d74de45534abb15d7c00cbfa49c3a04ea01e2b69 Author: Robert O Butts <rob...@users.noreply.github.com> AuthorDate: Tue May 26 09:36:58 2020 -0600 Add ORT/atstccfg Deterministic Config Generation (#4557) * Make ORT gen deterministic * Add ORT/atstccfg Line-Comment header Adds a header to the multipart file, with the line comment syntax of the file (if it has one). This lets ORT safely strip line comments with times for diffing. * Remove ORT/atstccfg unnecessary io param Removes TCCfg from GetAllConfigs, making the function Pure, which makes it possible/easier to unit test. * Change ORT/atstccfg magic string to const * Add ORT/atstccfg unit test for determinism --- lib/go-atscfg/astatsdotconfig.go | 1 + lib/go-atscfg/atscfg.go | 9 +- lib/go-atscfg/atsdotrules.go | 1 + lib/go-atscfg/bgfetchdotconfig.go | 1 + lib/go-atscfg/cachedotconfig.go | 8 +- lib/go-atscfg/cacheurldotconfig.go | 1 + lib/go-atscfg/chkconfig.go | 16 + lib/go-atscfg/dropqstringdotconfig.go | 1 + lib/go-atscfg/facts.go | 1 + lib/go-atscfg/headerrewritedotconfig.go | 1 + lib/go-atscfg/hostingdotconfig.go | 11 +- lib/go-atscfg/ipallowdotconfig.go | 19 + lib/go-atscfg/loggingdotconfig.go | 1 + lib/go-atscfg/loggingdotyaml.go | 1 + lib/go-atscfg/logsdotxml.go | 6 + lib/go-atscfg/packages.go | 14 + lib/go-atscfg/parentdotconfig.go | 6 +- lib/go-atscfg/plugindotconfig.go | 1 + lib/go-atscfg/recordsdotconfig.go | 1 + lib/go-atscfg/regexremapdotconfig.go | 1 + lib/go-atscfg/regexrevalidatedotconfig.go | 2 + lib/go-atscfg/remapdotconfig.go | 1 + lib/go-atscfg/servercachedotconfig.go | 10 +- lib/go-atscfg/serverunknown.go | 18 + lib/go-atscfg/setdscpdotconfig.go | 1 + lib/go-atscfg/sslmulticertdotconfig.go | 10 +- lib/go-atscfg/storagedotconfig.go | 1 + lib/go-atscfg/sysctldotconf.go | 1 + lib/go-atscfg/unknownconfig.go | 24 +- lib/go-atscfg/urisigningconfig.go | 1 + lib/go-atscfg/urlsigconfig.go | 16 +- lib/go-atscfg/volumedotconfig.go | 1 + traffic_ops/ort/atstccfg/atstccfg.go | 5 +- traffic_ops/ort/atstccfg/cfgfile/all.go | 13 +- .../ort/atstccfg/cfgfile/astatsdotconfig.go | 13 +- traffic_ops/ort/atstccfg/cfgfile/atsdotrules.go | 13 +- .../ort/atstccfg/cfgfile/bgfetchdotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/cachedotconfig.go | 4 +- .../ort/atstccfg/cfgfile/cacheurldotconfig.go | 6 +- traffic_ops/ort/atstccfg/cfgfile/cfgfile.go | 8 +- traffic_ops/ort/atstccfg/cfgfile/cfgfile_test.go | 469 ++++++++++++++++++++- traffic_ops/ort/atstccfg/cfgfile/chkconfig.go | 4 +- .../ort/atstccfg/cfgfile/dropqstringdotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/facts.go | 4 +- .../ort/atstccfg/cfgfile/headerrewritedotconfig.go | 10 +- .../atstccfg/cfgfile/headerrewritemiddotconfig.go | 10 +- .../ort/atstccfg/cfgfile/hostingdotconfig.go | 6 +- .../ort/atstccfg/cfgfile/ipallowdotconfig.go | 8 +- .../ort/atstccfg/cfgfile/loggingdotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/loggingdotyaml.go | 4 +- .../ort/atstccfg/cfgfile/logsxmldotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/meta.go | 5 +- traffic_ops/ort/atstccfg/cfgfile/packages.go | 4 +- .../ort/atstccfg/cfgfile/parentdotconfig.go | 36 +- .../ort/atstccfg/cfgfile/plugindotconfig.go | 4 +- .../ort/atstccfg/cfgfile/recordsdotconfig.go | 4 +- .../ort/atstccfg/cfgfile/regexremapdotconfig.go | 10 +- .../atstccfg/cfgfile/regexrevalidatedotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/remapdotconfig.go | 55 +-- traffic_ops/ort/atstccfg/cfgfile/routing.go | 63 +-- .../ort/atstccfg/cfgfile/servercachedotconfig.go | 6 +- .../ort/atstccfg/cfgfile/serverunknownconfig.go | 5 +- .../ort/atstccfg/cfgfile/setdscpdotconfig.go | 4 +- .../ort/atstccfg/cfgfile/sslmulticertdotconfig.go | 4 +- .../ort/atstccfg/cfgfile/storagedotconfig.go | 4 +- traffic_ops/ort/atstccfg/cfgfile/sysctldotconf.go | 17 +- traffic_ops/ort/atstccfg/cfgfile/unknownconfig.go | 9 +- .../ort/atstccfg/cfgfile/urisigningconfig.go | 8 +- traffic_ops/ort/atstccfg/cfgfile/urlsigconfig.go | 20 +- .../ort/atstccfg/cfgfile/volumedotconfig.go | 4 +- traffic_ops/ort/atstccfg/config/config.go | 13 + traffic_ops/ort/atstccfg/plugin/hello_world.go | 1 + traffic_ops/ort/atstccfg/plugin/plugin_test.go | 1 + 73 files changed, 851 insertions(+), 210 deletions(-) diff --git a/lib/go-atscfg/astatsdotconfig.go b/lib/go-atscfg/astatsdotconfig.go index 0fbc0bf..8ea62d5 100644 --- a/lib/go-atscfg/astatsdotconfig.go +++ b/lib/go-atscfg/astatsdotconfig.go @@ -23,6 +23,7 @@ const AstatsSeparator = "=" const AstatsFileName = "astats.config" const ContentTypeAstatsDotConfig = ContentTypeTextASCII +const LineCommentAstatsDotConfig = LineCommentHash func MakeAStatsDotConfig( profileName string, diff --git a/lib/go-atscfg/atscfg.go b/lib/go-atscfg/atscfg.go index 2e38e4e..8798ed3 100644 --- a/lib/go-atscfg/atscfg.go +++ b/lib/go-atscfg/atscfg.go @@ -21,6 +21,7 @@ package atscfg import ( "errors" + "sort" "strconv" "strings" "time" @@ -36,6 +37,8 @@ const HeaderCommentDateFormat = "Mon Jan 2 15:04:05 MST 2006" const ContentTypeTextASCII = `text/plain; charset=us-ascii` +const LineCommentHash = "#" + type ServerCapability string type ServerInfo struct { @@ -103,10 +106,14 @@ func GenericProfileConfig( separator string, ) string { text := "" + + lines := []string{} for name, val := range paramData { name = trimParamUnderscoreNumSuffix(name) - text += name + separator + val + "\n" + lines = append(lines, name+separator+val+"\n") } + sort.Strings(lines) + text = strings.Join(lines, "") return text } diff --git a/lib/go-atscfg/atsdotrules.go b/lib/go-atscfg/atsdotrules.go index 5ea8f43..286d44e 100644 --- a/lib/go-atscfg/atsdotrules.go +++ b/lib/go-atscfg/atsdotrules.go @@ -24,6 +24,7 @@ import ( ) const ContentTypeATSDotRules = ContentTypeTextASCII +const LineCommentATSDotRules = LineCommentHash func MakeATSDotRules( profileName string, diff --git a/lib/go-atscfg/bgfetchdotconfig.go b/lib/go-atscfg/bgfetchdotconfig.go index 3480613..7629e40 100644 --- a/lib/go-atscfg/bgfetchdotconfig.go +++ b/lib/go-atscfg/bgfetchdotconfig.go @@ -24,6 +24,7 @@ import ( ) const ContentTypeBGFetchDotConfig = ContentTypeTextASCII +const LineCommentBGFetchDotConfig = LineCommentHash func MakeBGFetchDotConfig( cdnName tc.CDNName, diff --git a/lib/go-atscfg/cachedotconfig.go b/lib/go-atscfg/cachedotconfig.go index ba95e0e..7b23107 100644 --- a/lib/go-atscfg/cachedotconfig.go +++ b/lib/go-atscfg/cachedotconfig.go @@ -20,6 +20,7 @@ package atscfg */ import ( + "sort" "strings" "github.com/apache/trafficcontrol/lib/go-log" @@ -27,6 +28,7 @@ import ( ) const ContentTypeCacheDotConfig = ContentTypeTextASCII +const LineCommentCacheDotConfig = LineCommentHash type ProfileDS struct { Type tc.DSType @@ -60,10 +62,12 @@ func MakeCacheDotConfig( } } - text := "" + linesArr := []string{} for line, _ := range lines { - text += line + linesArr = append(linesArr, line) } + sort.Strings(linesArr) + text := strings.Join(linesArr, "") if text == "" { text = "\n" // If no params exist, don't send "not found," but an empty file. We know the profile exists. } diff --git a/lib/go-atscfg/cacheurldotconfig.go b/lib/go-atscfg/cacheurldotconfig.go index f6a077c..1f48110 100644 --- a/lib/go-atscfg/cacheurldotconfig.go +++ b/lib/go-atscfg/cacheurldotconfig.go @@ -27,6 +27,7 @@ import ( ) const ContentTypeCacheURLDotConfig = ContentTypeTextASCII +const LineCommentCacheURLDotConfig = LineCommentHash type CacheURLDS struct { OrgServerFQDN string diff --git a/lib/go-atscfg/chkconfig.go b/lib/go-atscfg/chkconfig.go index 581ca38..9d870c9 100644 --- a/lib/go-atscfg/chkconfig.go +++ b/lib/go-atscfg/chkconfig.go @@ -21,6 +21,7 @@ package atscfg import ( "encoding/json" + "sort" "github.com/apache/trafficcontrol/lib/go-log" ) @@ -28,12 +29,24 @@ import ( const ChkconfigFileName = `chkconfig` const ChkconfigParamConfigFile = `chkconfig` const ContentTypeChkconfig = ContentTypeTextASCII +const LineCommentChkconfig = LineCommentHash type ChkConfigEntry struct { Name string `json:"name"` Val string `json:"value"` } +type ChkConfigEntries []ChkConfigEntry + +func (e ChkConfigEntries) Len() int { return len(e) } +func (e ChkConfigEntries) Less(i, j int) bool { + if e[i].Name != e[j].Name { + return e[i].Name < e[j].Name + } + return e[i].Val < e[j].Val +} +func (e ChkConfigEntries) Swap(i, j int) { e[i], e[j] = e[j], e[i] } + // MakeChkconfig returns the 'chkconfig' ATS config file endpoint. // This is a JSON object, and should be served with an 'application/json' Content-Type. func MakeChkconfig( @@ -46,6 +59,9 @@ func MakeChkconfig( chkconfig = append(chkconfig, ChkConfigEntry{Name: name, Val: val}) } } + + sort.Sort(ChkConfigEntries(chkconfig)) + bts, err := json.Marshal(&chkconfig) if err != nil { // should never happen diff --git a/lib/go-atscfg/dropqstringdotconfig.go b/lib/go-atscfg/dropqstringdotconfig.go index 3c7c59b..68d9189 100644 --- a/lib/go-atscfg/dropqstringdotconfig.go +++ b/lib/go-atscfg/dropqstringdotconfig.go @@ -22,6 +22,7 @@ package atscfg const DropQStringDotConfigFileName = "drop_qstring.config" const DropQStringDotConfigParamName = "content" const ContentTypeDropQStringDotConfig = ContentTypeTextASCII +const LineCommentDropQStringDotConfig = LineCommentHash func MakeDropQStringDotConfig( profileName string, diff --git a/lib/go-atscfg/facts.go b/lib/go-atscfg/facts.go index 70102ce..c7e6eb6 100644 --- a/lib/go-atscfg/facts.go +++ b/lib/go-atscfg/facts.go @@ -20,6 +20,7 @@ package atscfg */ const ContentType12MFacts = ContentTypeTextASCII +const LineComment12MFacts = LineCommentHash func Make12MFacts( profileName string, diff --git a/lib/go-atscfg/headerrewritedotconfig.go b/lib/go-atscfg/headerrewritedotconfig.go index 083ee91..34a96ae 100644 --- a/lib/go-atscfg/headerrewritedotconfig.go +++ b/lib/go-atscfg/headerrewritedotconfig.go @@ -31,6 +31,7 @@ import ( const HeaderRewritePrefix = "hdr_rw_" const ContentTypeHeaderRewriteDotConfig = ContentTypeTextASCII +const LineCommentHeaderRewriteDotConfig = LineCommentHash const MaxOriginConnectionsNoMax = 0 // 0 indicates no limit on origin connections diff --git a/lib/go-atscfg/hostingdotconfig.go b/lib/go-atscfg/hostingdotconfig.go index f3f53bc..5df86e9 100644 --- a/lib/go-atscfg/hostingdotconfig.go +++ b/lib/go-atscfg/hostingdotconfig.go @@ -20,6 +20,7 @@ package atscfg */ import ( + "sort" "strconv" "strings" @@ -29,6 +30,7 @@ import ( const HostingConfigFileName = `hosting.config` const HostingConfigParamConfigFile = `storage.config` const ContentTypeHostingDotConfig = ContentTypeTextASCII +const LineCommentHostingDotConfig = LineCommentHash const ParamDrivePrefix = "Drive_Prefix" const ParamRAMDrivePrefix = "RAM_Drive_Prefix" @@ -42,6 +44,7 @@ func MakeHostingDotConfig( ) string { text := GenericHeaderComment(string(serverName), toToolName, toURL) + lines := []string{} if _, ok := params[ParamRAMDrivePrefix]; ok { nextVolume := 1 if _, ok := params[ParamDrivePrefix]; ok { @@ -60,10 +63,14 @@ func MakeHostingDotConfig( seenOrigins[origin] = struct{}{} origin = strings.TrimPrefix(origin, `http://`) origin = strings.TrimPrefix(origin, `https://`) - text += `hostname=` + origin + ` volume=` + strconv.Itoa(ramVolume) + "\n" + lines = append(lines, `hostname=`+origin+` volume=`+strconv.Itoa(ramVolume)+"\n") } } diskVolume := 1 // note this will actually be the RAM (RAM_Drive_Prefix) volume if there is no Drive_Prefix parameter. - text += `hostname=* volume=` + strconv.Itoa(diskVolume) + "\n" + + lines = append(lines, `hostname=* volume=`+strconv.Itoa(diskVolume)+"\n") + + sort.Strings(lines) + text += strings.Join(lines, "") return text } diff --git a/lib/go-atscfg/ipallowdotconfig.go b/lib/go-atscfg/ipallowdotconfig.go index 4593536..b851a51 100644 --- a/lib/go-atscfg/ipallowdotconfig.go +++ b/lib/go-atscfg/ipallowdotconfig.go @@ -21,6 +21,7 @@ package atscfg import ( "net" + "sort" "strconv" "strings" @@ -31,6 +32,7 @@ import ( const IPAllowConfigFileName = `ip_allow.config` const ContentTypeIPAllowDotConfig = ContentTypeTextASCII +const LineCommentIPAllowDotConfig = LineCommentHash type IPAllowData struct { Src string @@ -38,6 +40,20 @@ type IPAllowData struct { Method string } +type IPAllowDatas []IPAllowData + +func (is IPAllowDatas) Len() int { return len(is) } +func (is IPAllowDatas) Swap(i, j int) { is[i], is[j] = is[j], is[i] } +func (is IPAllowDatas) Less(i, j int) bool { + if is[i].Src != is[j].Src { + return is[i].Src < is[j].Src + } + if is[i].Action != is[j].Action { + return is[i].Action < is[j].Action + } + return is[i].Method < is[j].Method +} + const ParamPurgeAllowIP = "purge_allow_ip" const ParamCoalesceMaskLenV4 = "coalesce_masklen_v4" const ParamCoalesceNumberV4 = "coalesce_number_v4" @@ -233,6 +249,9 @@ func MakeIPAllowDotConfig( Method: MethodAll, }) + // order matters, so sort before adding the denys + sort.Sort(IPAllowDatas(ipAllowData)) + // end with a deny ipAllowData = append(ipAllowData, IPAllowData{ Src: `0.0.0.0-255.255.255.255`, diff --git a/lib/go-atscfg/loggingdotconfig.go b/lib/go-atscfg/loggingdotconfig.go index fdb24fc..0d9f375 100644 --- a/lib/go-atscfg/loggingdotconfig.go +++ b/lib/go-atscfg/loggingdotconfig.go @@ -30,6 +30,7 @@ const MaxLogObjects = 10 const LoggingFileName = "logging.config" const ContentTypeLoggingDotConfig = ContentTypeTextASCII +const LineCommentLoggingDotConfig = LineCommentHash // MakeStorageDotConfig creates storage.config for a given ATS Profile. // The paramData is the map of parameter names to values, for all parameters assigned to the given profile, with the config_file "storage.config". diff --git a/lib/go-atscfg/loggingdotyaml.go b/lib/go-atscfg/loggingdotyaml.go index 84851de..ab5fc00 100644 --- a/lib/go-atscfg/loggingdotyaml.go +++ b/lib/go-atscfg/loggingdotyaml.go @@ -28,6 +28,7 @@ import ( const LoggingYAMLFileName = "logging.yaml" const ContentTypeLoggingDotYAML = "application/yaml; charset=us-ascii" // Note YAML has no IANA standard mime type. This is one of several common usages, and is likely to be the standardized value. If you're reading this, please check IANA to see if YAML has been added, and change this to the IANA definition if so. Also note we include 'charset=us-ascii' because YAML is commonly UTF-8, but ATS is likely to be unable to handle UTF. +const LineCommentLoggingDotYAML = LineCommentHash func MakeLoggingDotYAML( profileName string, diff --git a/lib/go-atscfg/logsdotxml.go b/lib/go-atscfg/logsdotxml.go index 991b411..72e6525 100644 --- a/lib/go-atscfg/logsdotxml.go +++ b/lib/go-atscfg/logsdotxml.go @@ -27,12 +27,18 @@ import ( const LogsXMLFileName = "logs_xml.config" const ContentTypeLogsDotXML = `text/xml` +const LineCommentLogsDotXML = `<!--` + func MakeLogsXMLDotConfig( profileName string, paramData map[string]string, // GetProfileParamData(tx, profile.ID, LoggingYAMLFileName) toToolName string, // tm.toolname global parameter (TODO: cache itself?) toURL string, // tm.url global parameter (TODO: cache itself?) ) string { + + // Note LineCommentLogsDotXML must be a single-line comment! + // But this file doesn't have a single-line format, so we use <!-- for the header and promise it's on a single line + // Note! if this file is ever changed to have multi-line comments, LineCommentLogsDotXML will have to be changed to the empty string. hdrComment := GenericHeaderComment(profileName, toToolName, toURL) hdrComment = strings.Replace(hdrComment, `# `, ``, -1) hdrComment = strings.Replace(hdrComment, "\n", ``, -1) diff --git a/lib/go-atscfg/packages.go b/lib/go-atscfg/packages.go index b675072..f148d8a 100644 --- a/lib/go-atscfg/packages.go +++ b/lib/go-atscfg/packages.go @@ -21,6 +21,7 @@ package atscfg import ( "encoding/json" + "sort" "github.com/apache/trafficcontrol/lib/go-log" ) @@ -29,12 +30,24 @@ const PackagesFileName = `packages` const PackagesParamConfigFile = `package` const ContentTypePackages = ContentTypeTextASCII +const LineCommentPackages = "" type Package struct { Name string `json:"name"` Version string `json:"version"` } +type Packages []Package + +func (ps Packages) Len() int { return len(ps) } +func (ps Packages) Less(i, j int) bool { + if ps[i].Name != ps[j].Name { + return ps[i].Name < ps[j].Name + } + return ps[i].Version < ps[j].Version +} +func (ps Packages) Swap(i, j int) { ps[i], ps[j] = ps[j], ps[i] } + // MakePackages returns the 'packages' ATS config file endpoint. // This is a JSON object, and should be served with an 'application/json' Content-Type. func MakePackages( @@ -46,6 +59,7 @@ func MakePackages( packages = append(packages, Package{Name: name, Version: version}) } } + sort.Sort(Packages(packages)) bts, err := json.Marshal(&packages) if err != nil { // should never happen diff --git a/lib/go-atscfg/parentdotconfig.go b/lib/go-atscfg/parentdotconfig.go index a80a7e2..621cf3e 100644 --- a/lib/go-atscfg/parentdotconfig.go +++ b/lib/go-atscfg/parentdotconfig.go @@ -32,6 +32,7 @@ import ( ) const ContentTypeParentDotConfig = ContentTypeTextASCII +const LineCommentParentDotConfig = LineCommentHash const ParentConfigParamQStringHandling = "psel.qstring_handling" const ParentConfigParamMSOAlgorithm = "mso.algorithm" @@ -170,8 +171,7 @@ func MakeParentDotConfig( serverParams map[string]string, // getParentConfigServerProfileParams(serverID) parentInfos map[OriginHost][]ParentInfo, // getParentInfo(profileID, parentCachegroupID, secondaryParentCachegroupID) ) string { - - // parentInfos := makeParentInfo(serverInfo) + sort.Sort(ParentConfigDSTopLevelSortByName(parentConfigDSes)) nameVersionStr := GetNameVersionStringFromToolNameAndURL(toToolName, toURL) hdr := HeaderCommentWithTOVersionStr(serverInfo.HostName, nameVersionStr) @@ -257,8 +257,6 @@ func MakeParentDotConfig( roundRobin := `round_robin=consistent_hash` goDirect := `go_direct=false` - sort.Sort(ParentConfigDSTopLevelSortByName(parentConfigDSes)) - for _, ds := range parentConfigDSes { parents, secondaryParents := getParentStrs(ds, parentInfos[DeliveryServicesAllParentsKey], atsMajorVer) diff --git a/lib/go-atscfg/plugindotconfig.go b/lib/go-atscfg/plugindotconfig.go index 5a9eb5a..b4e45cf 100644 --- a/lib/go-atscfg/plugindotconfig.go +++ b/lib/go-atscfg/plugindotconfig.go @@ -22,6 +22,7 @@ package atscfg const PluginSeparator = " " const PluginFileName = "plugin.config" const ContentTypePluginDotConfig = ContentTypeTextASCII +const LineCommentPluginDotConfig = LineCommentHash func MakePluginDotConfig( profileName string, diff --git a/lib/go-atscfg/recordsdotconfig.go b/lib/go-atscfg/recordsdotconfig.go index 18aa3f8..4c50400 100644 --- a/lib/go-atscfg/recordsdotconfig.go +++ b/lib/go-atscfg/recordsdotconfig.go @@ -26,6 +26,7 @@ import ( const RecordsSeparator = " " const RecordsFileName = "records.config" const ContentTypeRecordsDotConfig = ContentTypeTextASCII +const LineCommentRecordsDotConfig = LineCommentHash func MakeRecordsDotConfig( profileName string, diff --git a/lib/go-atscfg/regexremapdotconfig.go b/lib/go-atscfg/regexremapdotconfig.go index f726793..76447c1 100644 --- a/lib/go-atscfg/regexremapdotconfig.go +++ b/lib/go-atscfg/regexremapdotconfig.go @@ -27,6 +27,7 @@ import ( ) const ContentTypeRegexRemapDotConfig = ContentTypeTextASCII +const LineCommentRegexRemapDotConfig = LineCommentHash type CDNDS struct { OrgServerFQDN string diff --git a/lib/go-atscfg/regexrevalidatedotconfig.go b/lib/go-atscfg/regexrevalidatedotconfig.go index ad614f9..a3fc9c1 100644 --- a/lib/go-atscfg/regexrevalidatedotconfig.go +++ b/lib/go-atscfg/regexrevalidatedotconfig.go @@ -41,6 +41,7 @@ const JobKeywordPurge = "PURGE" const RegexRevalidateMinTTL = time.Hour const ContentTypeRegexRevalidateDotConfig = ContentTypeTextASCII +const LineCommentRegexRevalidateDotConfig = LineCommentHash type Job struct { AssetURL string @@ -71,6 +72,7 @@ func MakeRegexRevalidateDotConfig( maxDays := DefaultMaxRevalDurationDays if maxDaysStrs := params[RegexRevalidateMaxRevalDurationDaysParamName]; len(maxDaysStrs) > 0 { + sort.Strings(maxDaysStrs) if maxDays, err = strconv.Atoi(maxDaysStrs[0]); err != nil { // just use the first, if there were multiple params log.Warnln("making regex revalidate config: max days param '" + maxDaysStrs[0] + "' is not an integer, using default value!") maxDays = DefaultMaxRevalDurationDays diff --git a/lib/go-atscfg/remapdotconfig.go b/lib/go-atscfg/remapdotconfig.go index 7b91686..8532a6f 100644 --- a/lib/go-atscfg/remapdotconfig.go +++ b/lib/go-atscfg/remapdotconfig.go @@ -32,6 +32,7 @@ import ( const CacheURLParameterConfigFile = "cacheurl.config" const CacheKeyParameterConfigFile = "cachekey.config" const ContentTypeRemapDotConfig = ContentTypeTextASCII +const LineCommentRemapDotConfig = LineCommentHash type RemapConfigDSData struct { ID int diff --git a/lib/go-atscfg/servercachedotconfig.go b/lib/go-atscfg/servercachedotconfig.go index 9d1d29c..f436477 100644 --- a/lib/go-atscfg/servercachedotconfig.go +++ b/lib/go-atscfg/servercachedotconfig.go @@ -20,6 +20,7 @@ package atscfg */ import ( + "sort" "strconv" "strings" @@ -39,6 +40,8 @@ func MakeServerCacheDotConfig( ) string { text := GenericHeaderComment(string(serverName), toToolName, toURL) + lines := []string{} + seenOrigins := map[string]struct{}{} for _, ds := range dses { if ds.Type != tc.DSTypeHTTPNoCache { @@ -51,12 +54,13 @@ func MakeServerCacheDotConfig( originFQDN, originPort := GetOriginFQDNAndPort(ds.OrgServerFQDN) if originPort != nil { - text += `dest_domain=` + originFQDN + ` port=` + strconv.Itoa(*originPort) + ` scheme=http action=never-cache` + "\n" + lines = append(lines, `dest_domain=`+originFQDN+` port=`+strconv.Itoa(*originPort)+` scheme=http action=never-cache`+"\n") } else { - text += `dest_domain=` + originFQDN + ` scheme=http action=never-cache` + "\n" + lines = append(lines, `dest_domain=`+originFQDN+` scheme=http action=never-cache`+"\n") } } - return text + sort.Strings(lines) + return text + strings.Join(lines, "") } // TODO unit test diff --git a/lib/go-atscfg/serverunknown.go b/lib/go-atscfg/serverunknown.go index 68c3732..309c4f0 100644 --- a/lib/go-atscfg/serverunknown.go +++ b/lib/go-atscfg/serverunknown.go @@ -83,3 +83,21 @@ func SortParams(params map[string][]string) []Param { sort.Sort(Params(sortedParams)) return sortedParams } + +// GetServerUnknownConfigCommentType takes the same data as MakeUnknownConfig and returns the comment type for that config. +// In particular, it returns # unless there is a 'header' parameter, in which case it returns an empty string. +// Wwe don't actually know that the first characters of a custom header are a comment, or how many characters it might be. +func GetServerUnknownConfigCommentType( + serverName tc.CacheName, + serverDomain string, + toToolName string, + toURL string, + params map[string][]string, +) string { + for name, _ := range params { + if name == "header" { + return "" + } + } + return LineCommentHash +} diff --git a/lib/go-atscfg/setdscpdotconfig.go b/lib/go-atscfg/setdscpdotconfig.go index 3f2ee3c..a13576a 100644 --- a/lib/go-atscfg/setdscpdotconfig.go +++ b/lib/go-atscfg/setdscpdotconfig.go @@ -26,6 +26,7 @@ import ( ) const ContentTypeSetDSCPDotConfig = ContentTypeTextASCII +const LineCommentSetDSCPDotConfig = LineCommentHash func MakeSetDSCPDotConfig( cdnName tc.CDNName, diff --git a/lib/go-atscfg/sslmulticertdotconfig.go b/lib/go-atscfg/sslmulticertdotconfig.go index 64cd48b..d9b0139 100644 --- a/lib/go-atscfg/sslmulticertdotconfig.go +++ b/lib/go-atscfg/sslmulticertdotconfig.go @@ -20,6 +20,7 @@ package atscfg */ import ( + "sort" "strings" "github.com/apache/trafficcontrol/lib/go-log" @@ -27,6 +28,7 @@ import ( ) const ContentTypeSSLMultiCertDotConfig = ContentTypeTextASCII +const LineCommentSSLMultiCertDotConfig = LineCommentHash const SSLMultiCertConfigFileName = `ssl_multicert.config` type SSLMultiCertDS struct { @@ -58,15 +60,17 @@ func MakeSSLMultiCertDotConfig( toURL string, // tm.url global parameter (TODO: cache itself?) dses map[tc.DeliveryServiceName]SSLMultiCertDS, ) string { - text := GenericHeaderComment(string(cdnName), toToolName, toURL) + hdr := GenericHeaderComment(string(cdnName), toToolName, toURL) dses = GetSSLMultiCertDotConfigDeliveryServices(dses) + lines := []string{} for dsName, ds := range dses { cerName, keyName := GetSSLMultiCertDotConfigCertAndKeyName(dsName, ds) - text += `ssl_cert_name=` + cerName + "\t" + ` ssl_key_name=` + keyName + "\n" + lines = append(lines, `ssl_cert_name=`+cerName+"\t"+` ssl_key_name=`+keyName+"\n") } - return text + sort.Strings(lines) + return hdr + strings.Join(lines, "") } // GetSSLMultiCertDotConfigCertAndKeyName returns the cert file name and key file name for the given delivery service. diff --git a/lib/go-atscfg/storagedotconfig.go b/lib/go-atscfg/storagedotconfig.go index a78cdff..50123b1 100644 --- a/lib/go-atscfg/storagedotconfig.go +++ b/lib/go-atscfg/storagedotconfig.go @@ -27,6 +27,7 @@ import ( ) const ContentTypeStorageDotConfig = ContentTypeTextASCII +const LineCommentStorageDotConfig = LineCommentHash // MakeStorageDotConfig creates storage.config for a given ATS Profile. // The paramData is the map of parameter names to values, for all parameters assigned to the given profile, with the config_file "storage.config". diff --git a/lib/go-atscfg/sysctldotconf.go b/lib/go-atscfg/sysctldotconf.go index ba3c144..cbc51de 100644 --- a/lib/go-atscfg/sysctldotconf.go +++ b/lib/go-atscfg/sysctldotconf.go @@ -22,6 +22,7 @@ package atscfg const SysctlSeparator = " = " const SysctlFileName = "sysctl.conf" const ContentTypeSysctlDotConf = ContentTypeTextASCII +const LineCommentSysctlDotConf = LineCommentHash func MakeSysCtlDotConf( profileName string, diff --git a/lib/go-atscfg/unknownconfig.go b/lib/go-atscfg/unknownconfig.go index 255d3b1..1f4742e 100644 --- a/lib/go-atscfg/unknownconfig.go +++ b/lib/go-atscfg/unknownconfig.go @@ -20,6 +20,7 @@ package atscfg */ import ( + "sort" "strings" ) @@ -33,7 +34,7 @@ func MakeUnknownConfig( ) string { hdr := GenericHeaderComment(profileName, toToolName, toURL) - text := "" + lines := []string{} for paramName, paramVal := range paramData { if paramName == "header" { if paramVal == "none" { @@ -42,9 +43,28 @@ func MakeUnknownConfig( hdr = paramVal + "\n" } } else { - text += paramVal + "\n" + lines = append(lines, paramVal+"\n") } } + sort.Strings(lines) + text := strings.Join(lines, "") text = strings.Replace(text, "__RETURN__", "\n", -1) return hdr + text } + +// GetUnknownConfigCommentType takes the same data as MakeUnknownConfig and returns the comment type for that config. +// In particular, it returns # unless there is a 'header' parameter, in which case it returns an empty string. +// Wwe don't actually know that the first characters of a custom header are a comment, or how many characters it might be. +func GetUnknownConfigCommentType( + profileName string, + paramData map[string]string, + toToolName string, + toURL string, +) string { + for paramName, _ := range paramData { + if paramName == "header" { + return "" + } + } + return LineCommentHash +} diff --git a/lib/go-atscfg/urisigningconfig.go b/lib/go-atscfg/urisigningconfig.go index a9db57e..a5ff635 100644 --- a/lib/go-atscfg/urisigningconfig.go +++ b/lib/go-atscfg/urisigningconfig.go @@ -20,6 +20,7 @@ package atscfg */ const ContentTypeURISigningDotConfig = `application/json; charset=us-ascii` +const LineCommentURISigningDotConfig = "" func MakeURISigningConfig( uriSigningKeysBts []byte, diff --git a/lib/go-atscfg/urlsigconfig.go b/lib/go-atscfg/urlsigconfig.go index 938414a..0193ae2 100644 --- a/lib/go-atscfg/urlsigconfig.go +++ b/lib/go-atscfg/urlsigconfig.go @@ -20,11 +20,15 @@ package atscfg */ import ( + "sort" "strings" "github.com/apache/trafficcontrol/lib/go-tc" ) +const ContentTypeURLSig = ContentTypeTextASCII +const LineCommentURLSig = LineCommentHash + func MakeURLSigConfig( profileName string, urlSigKeys tc.URLSigKeys, @@ -37,14 +41,22 @@ func MakeURLSigConfig( sep := " = " text := hdr + + paramLines := []string{} for paramName, paramVal := range paramData { if len(urlSigKeys) == 0 || !strings.HasPrefix(paramName, "key") { - text += paramName + sep + paramVal + "\n" + paramLines = append(paramLines, paramName+sep+paramVal+"\n") } } + sort.Strings(paramLines) + text += strings.Join(paramLines, "") + keyLines := []string{} for key, val := range urlSigKeys { - text += key + sep + val + "\n" + keyLines = append(keyLines, key+sep+val+"\n") } + sort.Strings(keyLines) + text += strings.Join(keyLines, "") + return text } diff --git a/lib/go-atscfg/volumedotconfig.go b/lib/go-atscfg/volumedotconfig.go index af92fb4..bef49e9 100644 --- a/lib/go-atscfg/volumedotconfig.go +++ b/lib/go-atscfg/volumedotconfig.go @@ -24,6 +24,7 @@ import ( ) const ContentTypeVolumeDotConfig = ContentTypeTextASCII +const LineCommentVolumeDotConfig = LineCommentHash // MakeVolumeDotConfig creates volume.config for a given ATS Profile. // The paramData is the map of parameter names to values, for all parameters assigned to the given profile, with the config_file "storage.config". diff --git a/traffic_ops/ort/atstccfg/atstccfg.go b/traffic_ops/ort/atstccfg/atstccfg.go index ee9ab87..0a77c62 100644 --- a/traffic_ops/ort/atstccfg/atstccfg.go +++ b/traffic_ops/ort/atstccfg/atstccfg.go @@ -50,6 +50,7 @@ package main import ( "fmt" "os" + "sort" "strings" "github.com/apache/trafficcontrol/lib/go-log" @@ -108,7 +109,7 @@ func main() { os.Exit(config.ExitCodeErrGeneric) } - configs, err := cfgfile.GetAllConfigs(tccfg, toData) + configs, err := cfgfile.GetAllConfigs(toData, tccfg.RevalOnly) if err != nil { log.Errorln("Getting config for'" + cfg.CacheHostName + "': " + err.Error()) os.Exit(config.ExitCodeErrGeneric) @@ -117,6 +118,8 @@ func main() { modifyFilesData := plugin.ModifyFilesData{Cfg: tccfg, TOData: toData, Files: configs} configs = plugins.ModifyFiles(modifyFilesData) + sort.Sort(config.ATSConfigFiles(configs)) + if err := cfgfile.WriteConfigs(configs, os.Stdout); err != nil { log.Errorln("Writing configs for '" + cfg.CacheHostName + "': " + err.Error()) os.Exit(config.ExitCodeErrGeneric) diff --git a/traffic_ops/ort/atstccfg/cfgfile/all.go b/traffic_ops/ort/atstccfg/cfgfile/all.go index d006a88..edf3be1 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/all.go +++ b/traffic_ops/ort/atstccfg/cfgfile/all.go @@ -36,7 +36,7 @@ import ( ) // GetAllConfigs gets all config files for cfg.CacheHostName. -func GetAllConfigs(cfg config.TCCfg, toData *config.TOData) ([]config.ATSConfigFile, error) { +func GetAllConfigs(toData *config.TOData, revalOnly bool) ([]config.ATSConfigFile, error) { meta, err := GetMeta(toData) if err != nil { return nil, errors.New("creating meta: " + err.Error()) @@ -45,10 +45,10 @@ func GetAllConfigs(cfg config.TCCfg, toData *config.TOData) ([]config.ATSConfigF hasSSLMultiCertConfig := false configs := []config.ATSConfigFile{} for _, fi := range meta.ConfigFiles { - if cfg.RevalOnly && fi.FileNameOnDisk != atscfg.RegexRevalidateFileName { + if revalOnly && fi.FileNameOnDisk != atscfg.RegexRevalidateFileName { continue } - txt, contentType, err := GetConfigFile(toData, fi) + txt, contentType, lineComment, err := GetConfigFile(toData, fi) if err != nil { return nil, errors.New("getting config file '" + fi.APIURI + "': " + err.Error()) } @@ -56,7 +56,7 @@ func GetAllConfigs(cfg config.TCCfg, toData *config.TOData) ([]config.ATSConfigF hasSSLMultiCertConfig = true } txt = PreprocessConfigFile(toData.Server, txt) - configs = append(configs, config.ATSConfigFile{ATSConfigMetaDataConfigFile: fi, Text: txt, ContentType: contentType}) + configs = append(configs, config.ATSConfigFile{ATSConfigMetaDataConfigFile: fi, Text: txt, ContentType: contentType, LineComment: lineComment}) } if hasSSLMultiCertConfig { @@ -71,13 +71,15 @@ func GetAllConfigs(cfg config.TCCfg, toData *config.TOData) ([]config.ATSConfigF } const HdrConfigFilePath = "Path" +const HdrLineComment = "Line-Comment" // WriteConfigs writes the given configs as a RFC2046ยง5.1 MIME multipart/mixed message. func WriteConfigs(configs []config.ATSConfigFile, output io.Writer) error { w := multipart.NewWriter(output) // Create a unique boundary. Because we're using a text encoding, we need to make sure the boundary text doesn't occur in any body. - boundary := w.Boundary() + // Always start with the same random UUID, so generating twice diffs the same (except in the unlikely chance this string is in a config somewhere). + boundary := `dc5p7zOLNkyTzdcZSme6tg` // random UUID randSet := `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ` for _, cfg := range configs { for strings.Contains(cfg.Text, boundary) { @@ -93,6 +95,7 @@ func WriteConfigs(configs []config.ATSConfigFile, output io.Writer) error { for _, cfg := range configs { hdr := map[string][]string{ rfc.ContentType: {cfg.ContentType}, + HdrLineComment: {cfg.LineComment}, HdrConfigFilePath: {filepath.Join(cfg.Location, cfg.FileNameOnDisk)}, } partW, err := w.CreatePart(hdr) diff --git a/traffic_ops/ort/atstccfg/cfgfile/astatsdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/astatsdotconfig.go index 32d09b7..c90d5c4 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/astatsdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/astatsdotconfig.go @@ -21,10 +21,11 @@ package cfgfile import ( "github.com/apache/trafficcontrol/lib/go-atscfg" + "github.com/apache/trafficcontrol/lib/go-log" "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileAstatsDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileAstatsDotConfig(toData *config.TOData) (string, string, string, error) { paramData := map[string]string{} // TODO add configFile query param to profile/parameters endpoint, to only get needed data for _, param := range toData.ServerParams { @@ -34,8 +35,16 @@ func GetConfigFileProfileAstatsDotConfig(toData *config.TOData) (string, string, if param.Name == "location" { continue } + if val, ok := paramData[param.Name]; ok { + if val < param.Value { + log.Errorln("data error: making astats.config: parameter '" + param.Name + "' had multiple values, ignoring '" + param.Value + "'") + continue + } else { + log.Errorln("data error: making astats.config: parameter '" + param.Name + "' had multiple values, ignoring '" + val + "'") + } + } paramData[param.Name] = param.Value } - return atscfg.MakeAStatsDotConfig(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeAstatsDotConfig, nil + return atscfg.MakeAStatsDotConfig(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeAstatsDotConfig, atscfg.LineCommentAstatsDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/atsdotrules.go b/traffic_ops/ort/atstccfg/cfgfile/atsdotrules.go index 40edddf..ee51c24 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/atsdotrules.go +++ b/traffic_ops/ort/atstccfg/cfgfile/atsdotrules.go @@ -21,12 +21,13 @@ package cfgfile import ( "github.com/apache/trafficcontrol/lib/go-atscfg" + "github.com/apache/trafficcontrol/lib/go-log" "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) const ATSDotRulesFileName = StorageFileName -func GetConfigFileProfileATSDotRules(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileATSDotRules(toData *config.TOData) (string, string, string, error) { paramData := map[string]string{} // TODO add configFile query param to profile/parameters endpoint, to only get needed data for _, param := range toData.ServerParams { @@ -36,7 +37,15 @@ func GetConfigFileProfileATSDotRules(toData *config.TOData) (string, string, err if param.Name == "location" { continue } + if val, ok := paramData[param.Name]; ok { + if val < param.Value { + log.Errorln("data error: making ats.rules: parameter '" + param.Name + "' had multiple values, ignoring '" + param.Value + "'") + continue + } else { + log.Errorln("data error: making ats.rules: parameter '" + param.Name + "' had multiple values, ignoring '" + val + "'") + } + } paramData[param.Name] = param.Value } - return atscfg.MakeATSDotRules(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeATSDotRules, nil + return atscfg.MakeATSDotRules(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeATSDotRules, atscfg.LineCommentATSDotRules, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/bgfetchdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/bgfetchdotconfig.go index a9e56c7..d0de192 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/bgfetchdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/bgfetchdotconfig.go @@ -25,6 +25,6 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNBGFetchDotConfig(toData *config.TOData) (string, string, error) { - return atscfg.MakeBGFetchDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL), atscfg.ContentTypeBGFetchDotConfig, nil +func GetConfigFileCDNBGFetchDotConfig(toData *config.TOData) (string, string, string, error) { + return atscfg.MakeBGFetchDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL), atscfg.ContentTypeBGFetchDotConfig, atscfg.LineCommentBGFetchDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/cachedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/cachedotconfig.go index 7c27447..71fb566 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/cachedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/cachedotconfig.go @@ -25,7 +25,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileCacheDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileCacheDotConfig(toData *config.TOData) (string, string, string, error) { profileServerIDsMap := map[int]struct{}{} for _, sv := range toData.Servers { if sv.Profile != toData.Server.Profile { @@ -65,5 +65,5 @@ func GetConfigFileProfileCacheDotConfig(toData *config.TOData) (string, string, profileDSes = append(profileDSes, atscfg.ProfileDS{Type: *ds.Type, OriginFQDN: &origin}) } - return atscfg.MakeCacheDotConfig(toData.Server.Profile, profileDSes, toData.TOToolName, toData.TOURL), atscfg.ContentTypeCacheDotConfig, nil + return atscfg.MakeCacheDotConfig(toData.Server.Profile, profileDSes, toData.TOToolName, toData.TOURL), atscfg.ContentTypeCacheDotConfig, atscfg.LineCommentCacheDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/cacheurldotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/cacheurldotconfig.go index 11237d6..ae60a85 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/cacheurldotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/cacheurldotconfig.go @@ -25,7 +25,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNCacheURL(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDNCacheURL(toData *config.TOData, fileName string) (string, string, string, error) { dsIDs := map[int]struct{}{} for _, ds := range toData.DeliveryServices { if ds.ID != nil { @@ -60,9 +60,9 @@ func GetConfigFileCDNCacheURL(toData *config.TOData, fileName string) (string, s cfgDSes := atscfg.DeliveryServicesToCacheURLDSes(dsesWithServers) - return atscfg.MakeCacheURLDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, fileName, cfgDSes), atscfg.ContentTypeCacheURLDotConfig, nil + return atscfg.MakeCacheURLDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, fileName, cfgDSes), atscfg.ContentTypeCacheURLDotConfig, atscfg.LineCommentCacheURLDotConfig, nil } -func GetConfigFileCDNCacheURLPlain(toData *config.TOData) (string, string, error) { +func GetConfigFileCDNCacheURLPlain(toData *config.TOData) (string, string, string, error) { return GetConfigFileCDNCacheURL(toData, "cacheurl.config") } diff --git a/traffic_ops/ort/atstccfg/cfgfile/cfgfile.go b/traffic_ops/ort/atstccfg/cfgfile/cfgfile.go index ab90c9b..de4813d 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/cfgfile.go +++ b/traffic_ops/ort/atstccfg/cfgfile/cfgfile.go @@ -418,8 +418,12 @@ func ParamsToMap(params []tc.Parameter) map[string]string { mp := map[string]string{} for _, param := range params { if val, ok := mp[param.Name]; ok { - log.Errorln("config generation got multiple parameters for name '" + param.Name + "' - using '" + val + "'") - continue + if val < param.Value { + log.Errorln("config generation got multiple parameters for name '" + param.Name + "' - ignoring '" + param.Value + "'") + continue + } else { + log.Errorln("config generation got multiple parameters for name '" + param.Name + "' - ignoring '" + val + "'") + } } mp[param.Name] = param.Value } diff --git a/traffic_ops/ort/atstccfg/cfgfile/cfgfile_test.go b/traffic_ops/ort/atstccfg/cfgfile/cfgfile_test.go index 0aa1c54..5c41360 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/cfgfile_test.go +++ b/traffic_ops/ort/atstccfg/cfgfile/cfgfile_test.go @@ -21,9 +21,13 @@ package cfgfile import ( "bytes" + + "math/rand" "strings" "testing" + "time" + "github.com/apache/trafficcontrol/lib/go-atscfg" "github.com/apache/trafficcontrol/lib/go-tc" "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) @@ -55,13 +59,13 @@ func TestWriteConfigs(t *testing.T) { actual := buf.String() - expected0 := "Content-Type: text/plain\r\nPath: /my/config0/location/config0.txt\r\n\r\nconfig0\r\n" + expected0 := "Content-Type: text/plain\r\nLine-Comment: \r\nPath: /my/config0/location/config0.txt\r\n\r\nconfig0\r\n" if !strings.Contains(actual, expected0) { - t.Errorf("WriteConfigs expecte '%v' actual '%v'", expected0, actual) + t.Errorf("WriteConfigs expected '%v' actual '%v'", expected0, actual) } - expected1 := "Content-Type: text/csv\r\nPath: /my/config1/location/config1.txt\r\n\r\nconfig2,foo\r\n" + expected1 := "Content-Type: text/csv\r\nLine-Comment: \r\nPath: /my/config1/location/config1.txt\r\n\r\nconfig2,foo\r\n" if !strings.Contains(actual, expected1) { t.Errorf("WriteConfigs expected config1 '%v' actual '%v'", expected1, actual) } @@ -110,3 +114,462 @@ func TestPreprocessConfigFile(t *testing.T) { } } } + +// TestGetAllConfigsWriteConfigsDeterministic tests that WriteConfigs(GetAllConfigs()) is Deterministic. +// That is, that for the same input, it always produces the same output. +// +// Because Go map iteration is defined to be random, running it multiple times even on the exact same input could be different, if there's a determinism bug. +// But beyond that, we re-order slices whose order isn't semantically significant (e.g. params) and run it again. +// +func TestGetAllConfigsWriteConfigsDeterministic(t *testing.T) { + // TODO expand fake data. Currently, it's only making a remap.config. + toData := MakeFakeTOData() + revalOnly := false + configs, err := GetAllConfigs(toData, revalOnly) + if err != nil { + t.Fatalf("error getting configs: " + err.Error()) + } + buf := &bytes.Buffer{} + if err := WriteConfigs(configs, buf); err != nil { + t.Fatalf("error writing configs: " + err.Error()) + } + configStr := buf.String() + + configStr = removeComments(configStr) + + for i := 0; i < 10; i++ { + configs2, err := GetAllConfigs(toData, revalOnly) + if err != nil { + t.Fatalf("error getting configs2: " + err.Error()) + } + buf := &bytes.Buffer{} + if err := WriteConfigs(configs2, buf); err != nil { + t.Fatalf("error writing configs2: " + err.Error()) + } + configStr2 := buf.String() + + configStr2 = removeComments(configStr2) + + if configStr != configStr2 { + // This doesn't actually need to be fatal; but if there are differences, we don't want to spam the error 10 times. + t.Fatalf("multiple configs with the same data expected to be deterministically the same, actual '''%v''' and '''%v'''", configStr, configStr2) + } + } +} + +func removeComments(configs string) string { + lines := strings.Split(configs, "\n") + newLines := []string{} + for _, line := range lines { + if strings.Contains(line, "DO NOT EDIT") { + continue + } + newLines = append(newLines, line) + } + return strings.Join(newLines, "\n") +} + +func randBool() *bool { + b := rand.Int()%2 == 0 + return &b +} + +func randStr() *string { + chars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_" + num := 100 + s := "" + for i := 0; i < num; i++ { + s += string(chars[rand.Intn(len(chars))]) + } + return &s +} + +func randInt() *int { + i := rand.Int() + return &i +} + +func randInt64() *int64 { + i := int64(rand.Int63()) + return &i +} + +func randFloat64() *float64 { + f := rand.Float64() + return &f +} + +func randDSS() tc.DeliveryServiceServer { + return tc.DeliveryServiceServer{ + Server: randInt(), + DeliveryService: randInt(), + } +} + +func randDS() *tc.DeliveryServiceNullable { + deepCachingTypeNever := tc.DeepCachingTypeNever + dsTypeHTTP := tc.DSTypeHTTP + protocol := tc.DSProtocolHTTP + return &tc.DeliveryServiceNullable{ + EcsEnabled: *randBool(), + RangeSliceBlockSize: randInt(), + DeliveryServiceNullableV14: tc.DeliveryServiceNullableV14{ + ConsistentHashRegex: randStr(), + ConsistentHashQueryParams: []string{ + *randStr(), + *randStr(), + }, + MaxOriginConnections: randInt(), + DeliveryServiceNullableV13: tc.DeliveryServiceNullableV13{ + DeepCachingType: &deepCachingTypeNever, + FQPacingRate: randInt(), + SigningAlgorithm: randStr(), + Tenant: randStr(), + TRResponseHeaders: randStr(), + TRRequestHeaders: randStr(), + DeliveryServiceNullableV12: tc.DeliveryServiceNullableV12{ + DeliveryServiceNullableV11: tc.DeliveryServiceNullableV11{ + Active: randBool(), + AnonymousBlockingEnabled: randBool(), + CacheURL: randStr(), + CCRDNSTTL: randInt(), + CDNID: randInt(), + CDNName: randStr(), + CheckPath: randStr(), + DisplayName: randStr(), + DNSBypassCNAME: randStr(), + DNSBypassIP: randStr(), + DNSBypassIP6: randStr(), + DNSBypassTTL: randInt(), + DSCP: randInt(), + EdgeHeaderRewrite: randStr(), + GeoLimit: randInt(), + GeoLimitCountries: randStr(), + GeoLimitRedirectURL: randStr(), + GeoProvider: randInt(), + GlobalMaxMBPS: randInt(), + GlobalMaxTPS: randInt(), + HTTPBypassFQDN: randStr(), + ID: randInt(), + InfoURL: randStr(), + InitialDispersion: randInt(), + IPV6RoutingEnabled: randBool(), + LastUpdated: &tc.TimeNoMod{Time: time.Now()}, + LogsEnabled: randBool(), + LongDesc: randStr(), + LongDesc1: randStr(), + LongDesc2: randStr(), + MatchList: &[]tc.DeliveryServiceMatch{ + tc.DeliveryServiceMatch{ + Type: tc.DSMatchTypeHostRegex, + SetNumber: 0, + Pattern: `\.*foo\.*`, + }, + }, + MaxDNSAnswers: randInt(), + MidHeaderRewrite: randStr(), + MissLat: randFloat64(), + MissLong: randFloat64(), + MultiSiteOrigin: randBool(), + OriginShield: randStr(), + OrgServerFQDN: randStr(), + ProfileDesc: randStr(), + ProfileID: randInt(), + ProfileName: randStr(), + Protocol: &protocol, + QStringIgnore: randInt(), + RangeRequestHandling: randInt(), + RegexRemap: randStr(), + RegionalGeoBlocking: randBool(), + RemapText: randStr(), + RoutingName: randStr(), + Signed: *randBool(), + SSLKeyVersion: randInt(), + TenantID: randInt(), + Type: &dsTypeHTTP, + TypeID: randInt(), + XMLID: randStr(), + ExampleURLs: []string{ + *randStr(), + *randStr(), + }, + }, + }, + }, + }, + } +} + +func randServer() *tc.Server { + return &tc.Server{ + Cachegroup: *randStr(), + CachegroupID: *randInt(), + CDNID: *randInt(), + CDNName: *randStr(), + DomainName: *randStr(), + FQDN: &*randStr(), + FqdnTime: time.Now(), + GUID: *randStr(), + HostName: *randStr(), + HTTPSPort: *randInt(), + ID: *randInt(), + ILOIPAddress: *randStr(), + ILOIPGateway: *randStr(), + ILOIPNetmask: *randStr(), + ILOPassword: *randStr(), + ILOUsername: *randStr(), + InterfaceMtu: *randInt(), + InterfaceName: *randStr(), + IP6Address: *randStr(), + IP6IsService: *randBool(), + IP6Gateway: *randStr(), + IPAddress: *randStr(), + IPIsService: *randBool(), + IPGateway: *randStr(), + IPNetmask: *randStr(), + LastUpdated: tc.TimeNoMod{Time: time.Now()}, + MgmtIPAddress: *randStr(), + MgmtIPGateway: *randStr(), + MgmtIPNetmask: *randStr(), + OfflineReason: *randStr(), + PhysLocation: *randStr(), + PhysLocationID: *randInt(), + Profile: *randStr(), + ProfileDesc: *randStr(), + ProfileID: *randInt(), + Rack: *randStr(), + RevalPending: *randBool(), + RouterHostName: *randStr(), + RouterPortName: *randStr(), + Status: *randStr(), + StatusID: *randInt(), + TCPPort: *randInt(), + Type: *randStr(), + TypeID: *randInt(), + UpdPending: *randBool(), + XMPPID: *randStr(), + XMPPPasswd: *randStr(), + } +} + +func randCacheGroup() *tc.CacheGroupNullable { + return &tc.CacheGroupNullable{ + ID: randInt(), + Name: randStr(), + ShortName: randStr(), + Latitude: randFloat64(), + Longitude: randFloat64(), + // ParentName: randStr(), + // ParentCachegroupID: randInt(), + // SecondaryParentName: randStr(), + // SecondaryParentCachegroupID: randInt(), + FallbackToClosest: randBool(), + Type: randStr(), + TypeID: randInt(), + LastUpdated: &tc.TimeNoMod{Time: time.Now()}, + Fallbacks: &[]string{ + *randStr(), + *randStr(), + }, + } +} + +func randParam() *tc.Parameter { + return &tc.Parameter{ + ConfigFile: *randStr(), + Name: *randStr(), + Value: *randStr(), + Profiles: []byte(`[]`), + } +} + +func randJob() *tc.Job { + return &tc.Job{ + Parameters: *randStr(), + Keyword: *randStr(), + AssetURL: *randStr(), + CreatedBy: *randStr(), + StartTime: *randStr(), + ID: *randInt64(), + DeliveryService: *randStr(), + } +} + +func randCDN() *tc.CDN { + return &tc.CDN{ + DNSSECEnabled: *randBool(), + DomainName: *randStr(), + Name: *randStr(), + } +} + +func randDSRs() *tc.DeliveryServiceRegexes { + return &tc.DeliveryServiceRegexes{ + Regexes: []tc.DeliveryServiceRegex{ + *randDSR(), + *randDSR(), + }, + DSName: *randStr(), + } +} + +func randDSR() *tc.DeliveryServiceRegex { + return &tc.DeliveryServiceRegex{ + Type: string(tc.DSMatchTypeHostRegex), + SetNumber: *randInt(), + Pattern: `\.*foo\.*`, + } +} + +func randCDNSSLKeys() *tc.CDNSSLKeys { + return &tc.CDNSSLKeys{ + DeliveryService: *randStr(), + Certificate: tc.CDNSSLKeysCertificate{ + Crt: *randStr(), + Key: *randStr(), + }, + Hostname: *randStr(), + } +} + +func MakeFakeTOData() *config.TOData { + cg0 := *randCacheGroup() + cg0.ParentName = nil + cg0.ParentCachegroupID = nil + + cg1 := *randCacheGroup() + cg1.ParentName = cg0.Name + cg1.ParentCachegroupID = cg0.ID + + sv0 := *randServer() + sv1 := *randServer() + sv2 := *randServer() + + sv0.Cachegroup = *cg0.Name + sv1.Cachegroup = *cg0.Name + sv2.Cachegroup = *cg1.Name + + ds0 := *randDS() + ds1 := *randDS() + + dss := []tc.DeliveryServiceServer{ + tc.DeliveryServiceServer{ + Server: &sv0.ID, + DeliveryService: ds0.ID, + }, + tc.DeliveryServiceServer{ + Server: &sv0.ID, + DeliveryService: ds1.ID, + }, + tc.DeliveryServiceServer{ + Server: &sv1.ID, + DeliveryService: ds0.ID, + }, + } + + dsr0 := randDSRs() + dsr0.DSName = *ds0.XMLID + dsr0.Regexes[0].Pattern = `\.*foo\.*` + // ds1.Pattern = `\.*bar\.*` + + dsr1 := randDSRs() + dsr1.DSName = *ds1.XMLID + + return &config.TOData{ + CacheGroups: []tc.CacheGroupNullable{ + cg0, + cg1, + }, + GlobalParams: []tc.Parameter{ + *randParam(), + *randParam(), + *randParam(), + }, + ScopeParams: []tc.Parameter{ + *randParam(), + *randParam(), + *randParam(), + }, + ServerParams: []tc.Parameter{ + // configLocation := locationParams["remap.config"].Location + tc.Parameter{ + ConfigFile: "remap.config", + Name: "location", + Value: "/etc/trafficserver", + Profiles: []byte(`[]`), + }, + *randParam(), + *randParam(), + *randParam(), + }, + CacheKeyParams: []tc.Parameter{ + *randParam(), + *randParam(), + *randParam(), + }, + ParentConfigParams: []tc.Parameter{ + *randParam(), + *randParam(), + *randParam(), + }, + DeliveryServices: []tc.DeliveryServiceNullable{ + ds0, + ds1, + }, + Servers: []tc.Server{ + sv1, + sv2, + }, + DeliveryServiceServers: dss, + Server: sv0, + TOToolName: *randStr(), + TOURL: *randStr(), + Jobs: []tc.Job{ + *randJob(), + *randJob(), + }, + CDN: *randCDN(), + DeliveryServiceRegexes: []tc.DeliveryServiceRegexes{ + *dsr0, + *dsr1, + }, + URISigningKeys: map[tc.DeliveryServiceName][]byte{ + tc.DeliveryServiceName(*randStr()): []byte(*randStr()), + tc.DeliveryServiceName(*randStr()): []byte(*randStr()), + }, + URLSigKeys: map[tc.DeliveryServiceName]tc.URLSigKeys{ + tc.DeliveryServiceName(*randStr()): map[string]string{ + *randStr(): *randStr(), + *randStr(): *randStr(), + }, + tc.DeliveryServiceName(*randStr()): map[string]string{ + *randStr(): *randStr(), + *randStr(): *randStr(), + }, + }, + ServerCapabilities: map[int]map[atscfg.ServerCapability]struct{}{ + *randInt(): map[atscfg.ServerCapability]struct{}{ + atscfg.ServerCapability(*randStr()): struct{}{}, + atscfg.ServerCapability(*randStr()): struct{}{}, + }, + *randInt(): map[atscfg.ServerCapability]struct{}{ + atscfg.ServerCapability(*randStr()): struct{}{}, + atscfg.ServerCapability(*randStr()): struct{}{}, + }, + }, + DSRequiredCapabilities: map[int]map[atscfg.ServerCapability]struct{}{ + *randInt(): map[atscfg.ServerCapability]struct{}{ + atscfg.ServerCapability(*randStr()): struct{}{}, + atscfg.ServerCapability(*randStr()): struct{}{}, + }, + *randInt(): map[atscfg.ServerCapability]struct{}{ + atscfg.ServerCapability(*randStr()): struct{}{}, + atscfg.ServerCapability(*randStr()): struct{}{}, + }, + }, + SSLKeys: []tc.CDNSSLKeys{ + *randCDNSSLKeys(), + *randCDNSSLKeys(), + }, + } +} diff --git a/traffic_ops/ort/atstccfg/cfgfile/chkconfig.go b/traffic_ops/ort/atstccfg/cfgfile/chkconfig.go index ac56f0c..c96872d 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/chkconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/chkconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerChkconfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerChkconfig(toData *config.TOData) (string, string, string, error) { fileParams := map[string][]string{} for _, param := range toData.ServerParams { if param.ConfigFile != atscfg.ChkconfigParamConfigFile { @@ -33,5 +33,5 @@ func GetConfigFileServerChkconfig(toData *config.TOData) (string, string, error) fileParams[param.Name] = append(fileParams[param.Name], param.Value) } - return atscfg.MakeChkconfig(fileParams), atscfg.ContentTypeChkconfig, nil + return atscfg.MakeChkconfig(fileParams), atscfg.ContentTypeChkconfig, atscfg.LineCommentChkconfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/dropqstringdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/dropqstringdotconfig.go index 9cc7262..4474ea8 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/dropqstringdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/dropqstringdotconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileDropQStringDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileDropQStringDotConfig(toData *config.TOData) (string, string, string, error) { dropQStringVal := (*string)(nil) for _, param := range toData.ServerParams { if param.ConfigFile != atscfg.DropQStringDotConfigFileName { @@ -37,5 +37,5 @@ func GetConfigFileProfileDropQStringDotConfig(toData *config.TOData) (string, st break } - return atscfg.MakeDropQStringDotConfig(toData.Server.Profile, toData.TOToolName, toData.TOURL, dropQStringVal), atscfg.ContentTypeDropQStringDotConfig, nil + return atscfg.MakeDropQStringDotConfig(toData.Server.Profile, toData.TOToolName, toData.TOURL, dropQStringVal), atscfg.ContentTypeDropQStringDotConfig, atscfg.LineCommentDropQStringDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/facts.go b/traffic_ops/ort/atstccfg/cfgfile/facts.go index 43c1a63..6cace4f 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/facts.go +++ b/traffic_ops/ort/atstccfg/cfgfile/facts.go @@ -24,6 +24,6 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfile12MFacts(toData *config.TOData) (string, string, error) { - return atscfg.Make12MFacts(toData.Server.Profile, toData.TOToolName, toData.TOURL), atscfg.ContentType12MFacts, nil +func GetConfigFileProfile12MFacts(toData *config.TOData) (string, string, string, error) { + return atscfg.Make12MFacts(toData.Server.Profile, toData.TOToolName, toData.TOURL), atscfg.ContentType12MFacts, atscfg.LineComment12MFacts, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/headerrewritedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/headerrewritedotconfig.go index ee9446e..be13ba0 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/headerrewritedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/headerrewritedotconfig.go @@ -28,7 +28,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNHeaderRewrite(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDNHeaderRewrite(toData *config.TOData, fileName string) (string, string, string, error) { dsName := strings.TrimSuffix(strings.TrimPrefix(fileName, atscfg.HeaderRewritePrefix), atscfg.ConfigSuffix) // TODO verify prefix and suffix? Perl doesn't tcDS := tc.DeliveryServiceNullable{} @@ -40,16 +40,16 @@ func GetConfigFileCDNHeaderRewrite(toData *config.TOData, fileName string) (stri break } if tcDS.ID == nil { - return "", "", errors.New("ds '" + dsName + "' not found") + return "", "", "", errors.New("ds '" + dsName + "' not found") } if tcDS.CDNName == nil { - return "", "", errors.New("ds '" + dsName + "' missing cdn") + return "", "", "", errors.New("ds '" + dsName + "' missing cdn") } cfgDS, err := atscfg.HeaderRewriteDSFromDS(&tcDS) if err != nil { - return "", "", errors.New("converting ds to config ds: " + err.Error()) + return "", "", "", errors.New("converting ds to config ds: " + err.Error()) } dsServers := FilterDSS(toData.DeliveryServiceServers, map[int]struct{}{cfgDS.ID: {}}, nil) @@ -80,5 +80,5 @@ func GetConfigFileCDNHeaderRewrite(toData *config.TOData, fileName string) (stri assignedEdges = append(assignedEdges, cfgServer) } - return atscfg.MakeHeaderRewriteDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDS, assignedEdges), atscfg.ContentTypeHeaderRewriteDotConfig, nil + return atscfg.MakeHeaderRewriteDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDS, assignedEdges), atscfg.ContentTypeHeaderRewriteDotConfig, atscfg.LineCommentHeaderRewriteDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/headerrewritemiddotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/headerrewritemiddotconfig.go index 766f638..460e3b9 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/headerrewritemiddotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/headerrewritemiddotconfig.go @@ -28,7 +28,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNHeaderRewriteMid(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDNHeaderRewriteMid(toData *config.TOData, fileName string) (string, string, string, error) { dsName := strings.TrimSuffix(strings.TrimPrefix(fileName, atscfg.HeaderRewriteMidPrefix), atscfg.ConfigSuffix) // TODO verify prefix and suffix? Perl doesn't tcDS := tc.DeliveryServiceNullable{} @@ -40,16 +40,16 @@ func GetConfigFileCDNHeaderRewriteMid(toData *config.TOData, fileName string) (s break } if tcDS.ID == nil { - return "", "", errors.New("ds '" + dsName + "' not found") + return "", "", "", errors.New("ds '" + dsName + "' not found") } if tcDS.CDNName == nil { - return "", "", errors.New("ds '" + dsName + "' missing cdn") + return "", "", "", errors.New("ds '" + dsName + "' missing cdn") } cfgDS, err := atscfg.HeaderRewriteDSFromDS(&tcDS) if err != nil { - return "", "", errors.New("converting ds to config ds: " + err.Error()) + return "", "", "", errors.New("converting ds to config ds: " + err.Error()) } dsServers := FilterDSS(toData.DeliveryServiceServers, map[int]struct{}{cfgDS.ID: {}}, nil) @@ -113,5 +113,5 @@ func GetConfigFileCDNHeaderRewriteMid(toData *config.TOData, fileName string) (s assignedMids = append(assignedMids, cfgServer) } - return atscfg.MakeHeaderRewriteMidDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDS, assignedMids), atscfg.ContentTypeHeaderRewriteDotConfig, nil + return atscfg.MakeHeaderRewriteMidDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDS, assignedMids), atscfg.ContentTypeHeaderRewriteDotConfig, atscfg.LineCommentHeaderRewriteDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/hostingdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/hostingdotconfig.go index fc5f301..6c4ac36 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/hostingdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/hostingdotconfig.go @@ -31,7 +31,7 @@ import ( const ServerHostingDotConfigMidIncludeInactive = false const ServerHostingDotConfigEdgeIncludeInactive = true -func GetConfigFileServerHostingDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerHostingDotConfig(toData *config.TOData) (string, string, string, error) { fileParams := ParamsToMap(FilterParams(toData.ServerParams, atscfg.HostingConfigParamConfigFile, "", "", "")) cdnServers := map[tc.CacheName]tc.Server{} @@ -59,7 +59,7 @@ func GetConfigFileServerHostingDotConfig(toData *config.TOData) (string, string, dsServerMap := map[int]map[int]struct{}{} // set[dsID][serverID] for _, dss := range dsServers { if dss.Server == nil || dss.DeliveryService == nil { - return "", "", errors.New("deliveryserviceservers returned dss with nil values") + return "", "", "", errors.New("deliveryserviceservers returned dss with nil values") } if _, ok := dsServerMap[*dss.DeliveryService]; !ok { dsServerMap[*dss.DeliveryService] = map[int]struct{}{} @@ -121,5 +121,5 @@ func GetConfigFileServerHostingDotConfig(toData *config.TOData) (string, string, origins = append(origins, origin) } - return atscfg.MakeHostingDotConfig(tc.CacheName(toData.Server.HostName), toData.TOToolName, toData.TOURL, fileParams, origins), atscfg.ContentTypeHostingDotConfig, nil + return atscfg.MakeHostingDotConfig(tc.CacheName(toData.Server.HostName), toData.TOToolName, toData.TOURL, fileParams, origins), atscfg.ContentTypeHostingDotConfig, atscfg.LineCommentHostingDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/ipallowdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/ipallowdotconfig.go index 698abe9..8c7489c 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/ipallowdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/ipallowdotconfig.go @@ -28,20 +28,20 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerIPAllowDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerIPAllowDotConfig(toData *config.TOData) (string, string, string, error) { fileParams := ParamsToMultiMap(FilterParams(toData.ServerParams, atscfg.IPAllowConfigFileName, "", "", "")) cgMap := map[string]tc.CacheGroupNullable{} for _, cg := range toData.CacheGroups { if cg.Name == nil { - return "", "", errors.New("got cachegroup with nil name!'") + return "", "", "", errors.New("got cachegroup with nil name!'") } cgMap[*cg.Name] = cg } serverCG, ok := cgMap[toData.Server.Cachegroup] if !ok { - return "", "", errors.New("server cachegroup not in cachegroups!") + return "", "", "", errors.New("server cachegroup not in cachegroups!") } childCGs := map[string]tc.CacheGroupNullable{} @@ -59,5 +59,5 @@ func GetConfigFileServerIPAllowDotConfig(toData *config.TOData) (string, string, } } - return atscfg.MakeIPAllowDotConfig(tc.CacheName(toData.Server.HostName), tc.CacheType(toData.Server.Type), toData.TOToolName, toData.TOURL, fileParams, childServers), atscfg.ContentTypeIPAllowDotConfig, nil + return atscfg.MakeIPAllowDotConfig(tc.CacheName(toData.Server.HostName), tc.CacheType(toData.Server.Type), toData.TOToolName, toData.TOURL, fileParams, childServers), atscfg.ContentTypeIPAllowDotConfig, atscfg.LineCommentIPAllowDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/loggingdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/loggingdotconfig.go index 7593ab4..99b0648 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/loggingdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/loggingdotconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileLoggingDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileLoggingDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, atscfg.LoggingFileName, "", "", "location")) - return atscfg.MakeLoggingDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLoggingDotConfig, nil + return atscfg.MakeLoggingDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLoggingDotConfig, atscfg.LineCommentLoggingDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/loggingdotyaml.go b/traffic_ops/ort/atstccfg/cfgfile/loggingdotyaml.go index 642a631..22cfc21 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/loggingdotyaml.go +++ b/traffic_ops/ort/atstccfg/cfgfile/loggingdotyaml.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileLoggingDotYAML(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileLoggingDotYAML(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, atscfg.LoggingYAMLFileName, "", "", "location")) - return atscfg.MakeLoggingDotYAML(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLoggingDotYAML, nil + return atscfg.MakeLoggingDotYAML(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLoggingDotYAML, atscfg.LineCommentLoggingDotYAML, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/logsxmldotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/logsxmldotconfig.go index becfa40..32265d9 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/logsxmldotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/logsxmldotconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileLogsXMLDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileLogsXMLDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, atscfg.LogsXMLFileName, "", "", "location")) - return atscfg.MakeLogsXMLDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLogsDotXML, nil + return atscfg.MakeLogsXMLDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeLogsDotXML, atscfg.LineCommentLogsDotXML, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/meta.go b/traffic_ops/ort/atstccfg/cfgfile/meta.go index d4dfd00..655e513 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/meta.go +++ b/traffic_ops/ort/atstccfg/cfgfile/meta.go @@ -109,10 +109,7 @@ func GetMeta(toData *config.TOData) (*tc.ATSConfigMetaData, error) { } } - scopeParams := map[string]string{} - for _, param := range toData.ScopeParams { - scopeParams[param.ConfigFile] = param.Value - } + scopeParams := ParamsToMap(toData.ScopeParams) locationParams := map[string]atscfg.ConfigProfileParams{} for _, param := range toData.ServerParams { diff --git a/traffic_ops/ort/atstccfg/cfgfile/packages.go b/traffic_ops/ort/atstccfg/cfgfile/packages.go index 8f1857c..97e1120 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/packages.go +++ b/traffic_ops/ort/atstccfg/cfgfile/packages.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerPackages(toData *config.TOData) (string, string, error) { +func GetConfigFileServerPackages(toData *config.TOData) (string, string, string, error) { params := ParamsToMultiMap(FilterParams(toData.ServerParams, atscfg.PackagesParamConfigFile, "", "", "")) - return atscfg.MakePackages(params), atscfg.ContentTypePackages, nil + return atscfg.MakePackages(params), atscfg.ContentTypePackages, atscfg.LineCommentPackages, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/parentdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/parentdotconfig.go index 1b4a6ba..75b6eef 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/parentdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/parentdotconfig.go @@ -33,18 +33,18 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, string, error) { cgMap := map[string]tc.CacheGroupNullable{} for _, cg := range toData.CacheGroups { if cg.Name == nil { - return "", "", errors.New("got cachegroup with nil name!'") + return "", "", "", errors.New("got cachegroup with nil name!'") } cgMap[*cg.Name] = cg } serverCG, ok := cgMap[toData.Server.Cachegroup] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' not found in CacheGroups") } parentCGID := -1 @@ -52,15 +52,15 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, if serverCG.ParentName != nil && *serverCG.ParentName != "" { parentCG, ok := cgMap[*serverCG.ParentName] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' parent '" + *serverCG.ParentName + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' parent '" + *serverCG.ParentName + "' not found in CacheGroups") } if parentCG.ID == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") } parentCGID = *parentCG.ID if parentCG.Type == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") } parentCGType = *parentCG.Type } @@ -70,15 +70,15 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, if serverCG.SecondaryParentName != nil && *serverCG.SecondaryParentName != "" { parentCG, ok := cgMap[*serverCG.SecondaryParentName] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' secondary parent '" + *serverCG.SecondaryParentName + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' secondary parent '" + *serverCG.SecondaryParentName + "' not found in CacheGroups") } if parentCG.ID == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") } secondaryParentCGID = *parentCG.ID if parentCG.Type == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") } secondaryParentCGType = *parentCG.Type @@ -107,10 +107,10 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, log.Infoln("This cache Is Top Level!") for _, cg := range toData.CacheGroups { if cg.Type == nil { - return "", "", errors.New("cachegroup type is nil!") + return "", "", "", errors.New("cachegroup type is nil!") } if cg.Name == nil { - return "", "", errors.New("cachegroup type is nil!") + return "", "", "", errors.New("cachegroup type is nil!") } if *cg.Type != tc.CacheGroupOriginTypeName { @@ -120,14 +120,14 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, } } else { if toData.Server.Cachegroup == "" { - return "", "", errors.New("server cachegroup is nil!") + return "", "", "", errors.New("server cachegroup is nil!") } for _, cg := range toData.CacheGroups { if cg.Type == nil { - return "", "", errors.New("cachegroup type is nil!") + return "", "", "", errors.New("cachegroup type is nil!") } if cg.Name == nil { - return "", "", errors.New("cachegroup type is nil!") + return "", "", "", errors.New("cachegroup type is nil!") } if *cg.Name == toData.Server.Cachegroup { @@ -172,7 +172,7 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, parentServerDSes := map[int]map[int]struct{}{} // map[serverID][dsID] // cgServerDSes for _, dss := range cgDSServers { if dss.Server == nil || dss.DeliveryService == nil { - return "", "", errors.New("getting parent.config cachegroup parent server delivery service servers: got dss with nil members!") + return "", "", "", errors.New("getting parent.config cachegroup parent server delivery service servers: got dss with nil members!") } if parentServerDSes[*dss.Server] == nil { parentServerDSes[*dss.Server] = map[int]struct{}{} @@ -194,12 +194,12 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, atsMajorVer, err := atscfg.GetATSMajorVersionFromATSVersion(atsVersionParam) if err != nil { - return "", "", errors.New("getting ATS major version from version parameter (profile '" + toData.Server.Profile + "' configFile 'package' name 'trafficserver'): " + err.Error()) + return "", "", "", errors.New("getting ATS major version from version parameter (profile '" + toData.Server.Profile + "' configFile 'package' name 'trafficserver'): " + err.Error()) } parentConfigParamsWithProfiles, err := TCParamsToParamsWithProfiles(toData.ParentConfigParams) if err != nil { - return "", "", errors.New("unmarshalling parent.config parameters profiles: " + err.Error()) + return "", "", "", errors.New("unmarshalling parent.config parameters profiles: " + err.Error()) } // this is an optimization, to avoid looping over all params, for every DS. Instead, we loop over all params only once, and put them in a profile map. @@ -455,7 +455,7 @@ func GetConfigFileServerParentDotConfig(toData *config.TOData) (string, string, parentInfos := atscfg.MakeParentInfo(&serverInfo, serverCDNDomain, profileCaches, originServers) - return atscfg.MakeParentDotConfig(&serverInfo, atsMajorVer, toData.TOToolName, toData.TOURL, parentConfigDSes, serverParams, parentInfos), atscfg.ContentTypeParentDotConfig, nil + return atscfg.MakeParentDotConfig(&serverInfo, atsMajorVer, toData.TOToolName, toData.TOURL, parentConfigDSes, serverParams, parentInfos), atscfg.ContentTypeParentDotConfig, atscfg.LineCommentParentDotConfig, nil } // GetDSOrigins takes a map[deliveryServiceID]DeliveryService, and returns a map[DeliveryServiceID]OriginURI. diff --git a/traffic_ops/ort/atstccfg/cfgfile/plugindotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/plugindotconfig.go index ebd30fd..2e6698f 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/plugindotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/plugindotconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfilePluginDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfilePluginDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, atscfg.PluginFileName, "", "", "location")) - return atscfg.MakePluginDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypePluginDotConfig, nil + return atscfg.MakePluginDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypePluginDotConfig, atscfg.LineCommentPluginDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/recordsdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/recordsdotconfig.go index 58fe81e..f7064c8 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/recordsdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/recordsdotconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileRecordsDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileRecordsDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, atscfg.RecordsFileName, "", "", "location")) - return atscfg.MakeRecordsDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeRecordsDotConfig, nil + return atscfg.MakeRecordsDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeRecordsDotConfig, atscfg.LineCommentRecordsDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/regexremapdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/regexremapdotconfig.go index 6e718d8..fecf353 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/regexremapdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/regexremapdotconfig.go @@ -27,15 +27,15 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNRegexRemap(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDNRegexRemap(toData *config.TOData, fileName string) (string, string, string, error) { configSuffix := `.config` if !strings.HasPrefix(fileName, atscfg.RegexRemapPrefix) || !strings.HasSuffix(fileName, configSuffix) { - return `{"alerts":[{"level":"error","text":"Error - regex remap file '` + fileName + `' not of the form 'regex_remap_*.config! Please file a bug with Traffic Control, this should never happen."}]}`, "", config.ErrBadRequest + return `{"alerts":[{"level":"error","text":"Error - regex remap file '` + fileName + `' not of the form 'regex_remap_*.config! Please file a bug with Traffic Control, this should never happen."}]}`, "", "", config.ErrBadRequest } dsName := strings.TrimSuffix(strings.TrimPrefix(fileName, atscfg.RegexRemapPrefix), configSuffix) if dsName == "" { - return `{"alerts":[{"level":"error","text":"Error - regex remap file '` + fileName + `' has no delivery service name!"}]}`, "", config.ErrBadRequest + return `{"alerts":[{"level":"error","text":"Error - regex remap file '` + fileName + `' has no delivery service name!"}]}`, "", "", config.ErrBadRequest } // only send the requested DS to atscfg. The atscfg.Make will work correctly even if we send it other DSes, but this will prevent atscfg.DeliveryServicesToCDNDSes from logging errors about AnyMap and Steering DSes without origins. @@ -50,10 +50,10 @@ func GetConfigFileCDNRegexRemap(toData *config.TOData, fileName string) (string, ds = dsesDS } if ds.ID == nil { - return `{"alerts":[{"level":"error","text":"Error - delivery service '` + dsName + `' not found! Do you have a regex_remap_*.config location Parameter for a delivery service that doesn't exist?"}]}`, "", config.ErrNotFound + return `{"alerts":[{"level":"error","text":"Error - delivery service '` + dsName + `' not found! Do you have a regex_remap_*.config location Parameter for a delivery service that doesn't exist?"}]}`, "", "", config.ErrNotFound } cfgDSes := atscfg.DeliveryServicesToCDNDSes([]tc.DeliveryServiceNullable{ds}) - return atscfg.MakeRegexRemapDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, fileName, cfgDSes), atscfg.ContentTypeRegexRemapDotConfig, nil + return atscfg.MakeRegexRemapDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, fileName, cfgDSes), atscfg.ContentTypeRegexRemapDotConfig, atscfg.LineCommentRegexRemapDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/regexrevalidatedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/regexrevalidatedotconfig.go index 7018f28..8df14fb 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/regexrevalidatedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/regexrevalidatedotconfig.go @@ -26,7 +26,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNRegexRevalidateDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileCDNRegexRevalidateDotConfig(toData *config.TOData) (string, string, string, error) { params := map[string][]string{} for _, param := range toData.GlobalParams { if param.ConfigFile != atscfg.RegexRevalidateFileName { @@ -52,5 +52,5 @@ func GetConfigFileCDNRegexRevalidateDotConfig(toData *config.TOData) (string, st jobs = append(jobs, job) } - return atscfg.MakeRegexRevalidateDotConfig(tc.CDNName(toData.Server.CDNName), params, toData.TOToolName, toData.TOURL, jobs), atscfg.ContentTypeRegexRevalidateDotConfig, nil + return atscfg.MakeRegexRevalidateDotConfig(tc.CDNName(toData.Server.CDNName), params, toData.TOToolName, toData.TOURL, jobs), atscfg.ContentTypeRegexRevalidateDotConfig, atscfg.LineCommentRegexRevalidateDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/remapdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/remapdotconfig.go index f05124f..73c35b3 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/remapdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/remapdotconfig.go @@ -32,7 +32,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, string, error) { // TODO TOAPI add /servers?cdn=1 query param atsVersionParam := "" @@ -49,7 +49,7 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e atsMajorVer, err := atscfg.GetATSMajorVersionFromATSVersion(atsVersionParam) if err != nil { - return "", "", errors.New("getting ATS major version from version parameter (profile '" + toData.Server.Profile + "' configFile 'package' name 'trafficserver'): " + err.Error()) + return "", "", "", errors.New("getting ATS major version from version parameter (profile '" + toData.Server.Profile + "' configFile 'package' name 'trafficserver'): " + err.Error()) } dsIDs := map[int]struct{}{} @@ -167,24 +167,23 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e if paramValue == "STRING __HOSTNAME__" { paramValue = toData.Server.HostName + "." + toData.Server.DomainName // TODO strings.Replace to replace all anywhere, instead of just an exact match? } - serverPackageParamData[paramName] = paramValue - } - cacheURLParams := map[string]string{} - for _, param := range toData.ServerParams { - if param.ConfigFile != atscfg.CacheURLParameterConfigFile { - continue - } - if existingVal, ok := cacheURLParams[param.Name]; ok { - log.Warnln("generating remap.config: server profile '" + toData.Server.Profile + "' cacheurl.config has multiple parameters for '" + param.Name + "' - using '" + existingVal + "' and ignoring the rest!") - continue + if val, ok := serverPackageParamData[paramName]; ok { + if val < paramValue { + log.Errorln("remap config generation got multiple parameters for server package name '" + paramName + "' - ignoring '" + paramValue + "'") + continue + } else { + log.Errorln("config generation got multiple parameters for server package name '" + paramName + "' - ignoring '" + val + "'") + } } - cacheURLParams[param.Name] = param.Value + serverPackageParamData[paramName] = paramValue } + cacheURLParams := ParamsToMap(FilterParams(toData.ServerParams, atscfg.CacheURLParameterConfigFile, "", "", "")) + cacheKeyParamsWithProfiles, err := TCParamsToParamsWithProfiles(toData.CacheKeyParams) if err != nil { - return "", "", errors.New("decoding cache key parameter profiles: " + err.Error()) + return "", "", "", errors.New("decoding cache key parameter profiles: " + err.Error()) } cacheKeyParamsWithProfilesMap := ParameterWithProfilesToMap(cacheKeyParamsWithProfiles) @@ -204,9 +203,13 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e if _, ok := dsProfilesCacheKeyConfigParams[dsProfileID]; !ok { dsProfilesCacheKeyConfigParams[dsProfileID] = map[string]string{} } - if _, ok := dsProfilesCacheKeyConfigParams[dsProfileID][param.Name]; ok { - // TODO warn - continue + if val, ok := dsProfilesCacheKeyConfigParams[dsProfileID][param.Name]; ok { + if val < param.Value { + log.Errorln("remap config generation got multiple parameters for name '" + param.Name + "' - ignoring '" + param.Value + "'") + continue + } else { + log.Errorln("remap config generation got multiple parameters for name '" + param.Name + "' - ignoring '" + val + "'") + } } dsProfilesCacheKeyConfigParams[dsProfileID][param.Name] = param.Value } @@ -220,14 +223,14 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e cgMap := map[string]tc.CacheGroupNullable{} for _, cg := range toData.CacheGroups { if cg.Name == nil { - return "", "", errors.New("got cachegroup with nil name!'") + return "", "", "", errors.New("got cachegroup with nil name!'") } cgMap[*cg.Name] = cg } serverCG, ok := cgMap[toData.Server.Cachegroup] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' not found in CacheGroups") } parentCGID := -1 @@ -235,15 +238,15 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e if serverCG.ParentName != nil && *serverCG.ParentName != "" { parentCG, ok := cgMap[*serverCG.ParentName] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' parent '" + *serverCG.ParentName + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' parent '" + *serverCG.ParentName + "' not found in CacheGroups") } if parentCG.ID == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") } parentCGID = *parentCG.ID if parentCG.Type == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") } parentCGType = *parentCG.Type } @@ -253,15 +256,15 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e if serverCG.SecondaryParentName != nil && *serverCG.SecondaryParentName != "" { parentCG, ok := cgMap[*serverCG.SecondaryParentName] if !ok { - return "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' secondary parent '" + *serverCG.SecondaryParentName + "' not found in CacheGroups") + return "", "", "", errors.New("server '" + toData.Server.HostName + "' cachegroup '" + toData.Server.Cachegroup + "' secondary parent '" + *serverCG.SecondaryParentName + "' not found in CacheGroups") } if parentCG.ID == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil ID!'") } secondaryParentCGID = *parentCG.ID if parentCG.Type == nil { - return "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") + return "", "", "", errors.New("got cachegroup '" + *parentCG.Name + "' with nil Type!'") } secondaryParentCGType = *parentCG.Type @@ -285,7 +288,7 @@ func GetConfigFileServerRemapDotConfig(toData *config.TOData) (string, string, e SecondaryParentCacheGroupType: secondaryParentCGType, Type: toData.Server.Type, } - return atscfg.MakeRemapDotConfig(tc.CacheName(toData.Server.HostName), toData.TOToolName, toData.TOURL, atsMajorVer, cacheURLParams, dsProfilesCacheKeyConfigParams, serverPackageParamData, serverInfo, remapConfigDSData), atscfg.ContentTypeRemapDotConfig, nil + return atscfg.MakeRemapDotConfig(tc.CacheName(toData.Server.HostName), toData.TOToolName, toData.TOURL, atsMajorVer, cacheURLParams, dsProfilesCacheKeyConfigParams, serverPackageParamData, serverInfo, remapConfigDSData), atscfg.ContentTypeRemapDotConfig, atscfg.LineCommentRemapDotConfig, nil } type DeliveryServiceRegexesSortByTypeThenSetNum []tc.DeliveryServiceRegex diff --git a/traffic_ops/ort/atstccfg/cfgfile/routing.go b/traffic_ops/ort/atstccfg/cfgfile/routing.go index 4845e94..58a0aaa 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/routing.go +++ b/traffic_ops/ort/atstccfg/cfgfile/routing.go @@ -29,14 +29,14 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -var scopeConfigFileFuncs = map[string]func(toData *config.TOData, fileName string) (string, string, error){ +var scopeConfigFileFuncs = map[string]func(toData *config.TOData, fileName string) (string, string, string, error){ "cdns": GetConfigFileCDN, "servers": GetConfigFileServer, "profiles": GetConfigFileProfile, } // GetConfigFile returns the text of the generated config file, the MIME Content Type of the config file, and any error. -func GetConfigFile(toData *config.TOData, fileInfo tc.ATSConfigMetaDataConfigFile) (string, string, error) { +func GetConfigFile(toData *config.TOData, fileInfo tc.ATSConfigMetaDataConfigFile) (string, string, string, error) { path := fileInfo.APIURI // TODO remove the URL path parsing. It's a legacy from when config files were endpoints in the meta config. // We should replace it with actually calling the right file and name directly. @@ -47,7 +47,7 @@ func GetConfigFile(toData *config.TOData, fileInfo tc.ATSConfigMetaDataConfigFil pathParts := strings.Split(path, "/") if len(pathParts) < 8 { - return "", "", errors.New("unknown config file '" + path + "'") + return "", "", "", errors.New("unknown config file '" + path + "'") } scope := pathParts[3] resource := pathParts[4] @@ -59,27 +59,28 @@ func GetConfigFile(toData *config.TOData, fileInfo tc.ATSConfigMetaDataConfigFil return scopeConfigFileFunc(toData, fileName) } - return "", "", errors.New("unknown config file '" + fileInfo.APIURI + "'") + return "", "", "", errors.New("unknown config file '" + fileInfo.APIURI + "'") } type ConfigFilePrefixSuffixFunc struct { Prefix string Suffix string - Func func(toData *config.TOData, fileName string) (string, string, error) + Func func(toData *config.TOData, fileName string) (string, string, string, error) } -func GetConfigFileCDN(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDN(toData *config.TOData, fileName string) (string, string, string, error) { log.Infoln("GetConfigFileCDN cdn '" + toData.Server.CDNName + "' fileName '" + fileName + "'") txt := "" contentType := "" + lineComment := "" err := error(nil) if getCfgFunc, ok := CDNConfigFileFuncs()[fileName]; ok { - txt, contentType, err = getCfgFunc(toData) + txt, contentType, lineComment, err = getCfgFunc(toData) } else { for _, prefixSuffixFunc := range ConfigFileCDNPrefixSuffixFuncs { if strings.HasPrefix(fileName, prefixSuffixFunc.Prefix) && strings.HasSuffix(fileName, prefixSuffixFunc.Suffix) && len(fileName) > len(prefixSuffixFunc.Prefix)+len(prefixSuffixFunc.Suffix) { - txt, contentType, err = prefixSuffixFunc.Func(toData, fileName) + txt, contentType, lineComment, err = prefixSuffixFunc.Func(toData, fileName) break } } @@ -90,44 +91,45 @@ func GetConfigFileCDN(toData *config.TOData, fileName string) (string, string, e } if err != nil { - return "", "", err + return "", "", "", err } - return txt, contentType, nil + return txt, contentType, lineComment, nil } -func GetConfigFileProfile(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileProfile(toData *config.TOData, fileName string) (string, string, string, error) { log.Infoln("GetConfigFileProfile profile '" + toData.Server.Profile + "' fileName '" + fileName + "'") txt := "" contentType := "" + lineComment := "" err := error(nil) if getCfgFunc, ok := ProfileConfigFileFuncs()[fileName]; ok { - txt, contentType, err = getCfgFunc(toData) + txt, contentType, lineComment, err = getCfgFunc(toData) } else if strings.HasPrefix(fileName, "url_sig_") && strings.HasSuffix(fileName, ".config") && len(fileName) > len("url_sig_")+len(".config") { - txt, contentType, err = GetConfigFileProfileURLSigConfig(toData, fileName) + txt, contentType, lineComment, err = GetConfigFileProfileURLSigConfig(toData, fileName) } else if strings.HasPrefix(fileName, "uri_signing_") && strings.HasSuffix(fileName, ".config") && len(fileName) > len("uri_signing")+len(".config") { - txt, contentType, err = GetConfigFileProfileURISigningConfig(toData, fileName) + txt, contentType, lineComment, err = GetConfigFileProfileURISigningConfig(toData, fileName) } else { - txt, contentType, err = GetConfigFileProfileUnknownConfig(toData, fileName) + txt, contentType, lineComment, err = GetConfigFileProfileUnknownConfig(toData, fileName) } if err != nil { - return "", "", err + return "", "", "", err } - return txt, contentType, nil + return txt, contentType, lineComment, nil } // ConfigFileFuncs returns a map[scope][configFile]configFileFunc. -func ConfigFileFuncs() map[string]map[string]func(toData *config.TOData) (string, string, error) { - return map[string]map[string]func(toData *config.TOData) (string, string, error){ +func ConfigFileFuncs() map[string]map[string]func(toData *config.TOData) (string, string, string, error) { + return map[string]map[string]func(toData *config.TOData) (string, string, string, error){ "cdns": CDNConfigFileFuncs(), "servers": ServerConfigFileFuncs(), "profiles": ProfileConfigFileFuncs(), } } -func CDNConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, error) { - return map[string]func(toData *config.TOData) (string, string, error){ +func CDNConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, string, error) { + return map[string]func(toData *config.TOData) (string, string, string, error){ "regex_revalidate.config": GetConfigFileCDNRegexRevalidateDotConfig, "bg_fetch.config": GetConfigFileCDNBGFetchDotConfig, "ssl_multicert.config": GetConfigFileCDNSSLMultiCertDotConfig, @@ -143,8 +145,8 @@ var ConfigFileCDNPrefixSuffixFuncs = []ConfigFilePrefixSuffixFunc{ {"set_dscp_", ".config", GetConfigFileCDNSetDSCP}, } -func ProfileConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, error) { - return map[string]func(toData *config.TOData) (string, string, error){ +func ProfileConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, string, error) { + return map[string]func(toData *config.TOData) (string, string, string, error){ "12M_facts": GetConfigFileProfile12MFacts, "50-ats.rules": GetConfigFileProfileATSDotRules, "astats.config": GetConfigFileProfileAstatsDotConfig, @@ -161,8 +163,8 @@ func ProfileConfigFileFuncs() map[string]func(toData *config.TOData) (string, st } } -func ServerConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, error) { - return map[string]func(toData *config.TOData) (string, string, error){ +func ServerConfigFileFuncs() map[string]func(toData *config.TOData) (string, string, string, error) { + return map[string]func(toData *config.TOData) (string, string, string, error){ "parent.config": GetConfigFileServerParentDotConfig, "remap.config": GetConfigFileServerRemapDotConfig, "cache.config": GetConfigFileServerCacheDotConfig, @@ -173,18 +175,19 @@ func ServerConfigFileFuncs() map[string]func(toData *config.TOData) (string, str } } -func GetConfigFileServer(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileServer(toData *config.TOData, fileName string) (string, string, string, error) { log.Infoln("GetConfigFileServer server '" + toData.Server.HostName + "' fileName '" + fileName + "'") txt := "" contentType := "" + lineComment := "" err := error(nil) if getCfgFunc, ok := ServerConfigFileFuncs()[fileName]; ok { - txt, contentType, err = getCfgFunc(toData) + txt, contentType, lineComment, err = getCfgFunc(toData) } else { - txt, contentType, err = GetConfigFileServerUnknownConfig(toData, fileName) + txt, contentType, lineComment, err = GetConfigFileServerUnknownConfig(toData, fileName) } if err != nil { - return "", "", err + return "", "", "", err } - return txt, contentType, nil + return txt, contentType, lineComment, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/servercachedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/servercachedotconfig.go index 2f240c6..13fb58d 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/servercachedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/servercachedotconfig.go @@ -30,13 +30,13 @@ import ( const ServerCacheDotConfigIncludeInactiveDSes = false // TODO move to lib/go-atscfg -func GetConfigFileServerCacheDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileServerCacheDotConfig(toData *config.TOData) (string, string, string, error) { // TODO TOAPI add /servers?cdn=1 query param // TODO remove this, we generated the scope, we know it's right? Or should we have an extra safety check? if !strings.HasPrefix(string(toData.Server.Type), tc.MidTypePrefix) { // emulates Perl - return "", "", errors.New("Error - incorrect file scope for route used. Please use the profiles route.") + return "", "", "", errors.New("Error - incorrect file scope for route used. Please use the profiles route.") } dsData := map[tc.DeliveryServiceName]atscfg.ServerCacheConfigDS{} @@ -54,5 +54,5 @@ func GetConfigFileServerCacheDotConfig(toData *config.TOData) (string, string, e serverName := tc.CacheName(toData.Server.HostName) - return atscfg.MakeServerCacheDotConfig(serverName, toData.TOToolName, toData.TOURL, dsData), atscfg.ContentTypeCacheDotConfig, nil + return atscfg.MakeServerCacheDotConfig(serverName, toData.TOToolName, toData.TOURL, dsData), atscfg.ContentTypeCacheDotConfig, atscfg.LineCommentCacheDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/serverunknownconfig.go b/traffic_ops/ort/atstccfg/cfgfile/serverunknownconfig.go index 95bf799..96633e5 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/serverunknownconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/serverunknownconfig.go @@ -25,7 +25,8 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileServerUnknownConfig(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileServerUnknownConfig(toData *config.TOData, fileName string) (string, string, string, error) { params := ParamsToMultiMap(FilterParams(toData.ServerParams, fileName, "", "", "")) - return atscfg.MakeServerUnknown(tc.CacheName(toData.Server.HostName), toData.Server.DomainName, toData.TOToolName, toData.TOURL, params), atscfg.ContentTypeServerUnknownConfig, nil + lineComment := atscfg.GetServerUnknownConfigCommentType(tc.CacheName(toData.Server.HostName), toData.Server.DomainName, toData.TOToolName, toData.TOURL, params) + return atscfg.MakeServerUnknown(tc.CacheName(toData.Server.HostName), toData.Server.DomainName, toData.TOToolName, toData.TOURL, params), atscfg.ContentTypeServerUnknownConfig, lineComment, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/setdscpdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/setdscpdotconfig.go index 1693ddb..6f0e6ef 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/setdscpdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/setdscpdotconfig.go @@ -27,11 +27,11 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNSetDSCP(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileCDNSetDSCP(toData *config.TOData, fileName string) (string, string, string, error) { // TODO verify prefix, suffix, and that it's a number? Perl doesn't. dscpNumStr := fileName dscpNumStr = strings.TrimPrefix(dscpNumStr, "set_dscp_") dscpNumStr = strings.TrimSuffix(dscpNumStr, ".config") - return atscfg.MakeSetDSCPDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, dscpNumStr), atscfg.ContentTypeSetDSCPDotConfig, nil + return atscfg.MakeSetDSCPDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, dscpNumStr), atscfg.ContentTypeSetDSCPDotConfig, atscfg.LineCommentSetDSCPDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/sslmulticertdotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/sslmulticertdotconfig.go index 4407393..f40883b 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/sslmulticertdotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/sslmulticertdotconfig.go @@ -25,8 +25,8 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileCDNSSLMultiCertDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileCDNSSLMultiCertDotConfig(toData *config.TOData) (string, string, string, error) { cfgDSes := atscfg.DeliveryServicesToSSLMultiCertDSes(toData.DeliveryServices) - return atscfg.MakeSSLMultiCertDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDSes), atscfg.ContentTypeSSLMultiCertDotConfig, nil + return atscfg.MakeSSLMultiCertDotConfig(tc.CDNName(toData.Server.CDNName), toData.TOToolName, toData.TOURL, cfgDSes), atscfg.ContentTypeSSLMultiCertDotConfig, atscfg.LineCommentSSLMultiCertDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/storagedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/storagedotconfig.go index 8bd169d..01a824b 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/storagedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/storagedotconfig.go @@ -26,7 +26,7 @@ import ( const StorageFileName = "storage.config" -func GetConfigFileProfileStorageDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileStorageDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, StorageFileName, "", "", "location")) - return atscfg.MakeStorageDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeStorageDotConfig, nil + return atscfg.MakeStorageDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeStorageDotConfig, atscfg.LineCommentStorageDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/sysctldotconf.go b/traffic_ops/ort/atstccfg/cfgfile/sysctldotconf.go index 44e9ae5..6f5abcc 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/sysctldotconf.go +++ b/traffic_ops/ort/atstccfg/cfgfile/sysctldotconf.go @@ -24,18 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileSysCtlDotConf(toData *config.TOData) (string, string, error) { - paramData := map[string]string{} - // TODO add configFile query param to profile/parameters endpoint, to only get needed data - for _, param := range toData.ServerParams { - if param.ConfigFile != atscfg.SysctlFileName { - continue - } - if param.Name == "location" { - continue - } - paramData[param.Name] = param.Value - } - - return atscfg.MakeSysCtlDotConf(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeSysctlDotConf, nil +func GetConfigFileProfileSysCtlDotConf(toData *config.TOData) (string, string, string, error) { + paramData := ParamsToMap(FilterParams(toData.ServerParams, atscfg.SysctlFileName, "", "", "location")) + return atscfg.MakeSysCtlDotConf(toData.Server.Profile, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeSysctlDotConf, atscfg.LineCommentSysctlDotConf, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/unknownconfig.go b/traffic_ops/ort/atstccfg/cfgfile/unknownconfig.go index e6b75d4..2dd3e18 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/unknownconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/unknownconfig.go @@ -24,7 +24,7 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileUnknownConfig(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileProfileUnknownConfig(toData *config.TOData, fileName string) (string, string, string, error) { inScope := false for _, scopeParam := range toData.ScopeParams { if scopeParam.ConfigFile != fileName { @@ -37,8 +37,11 @@ func GetConfigFileProfileUnknownConfig(toData *config.TOData, fileName string) ( break } if !inScope { - return `{"alerts":[{"level":"error","text":"Error - incorrect file scope for route used. Please use the servers route."}]}`, "", config.ErrBadRequest + return `{"alerts":[{"level":"error","text":"Error - incorrect file scope for route used. Please use the servers route."}]}`, "", "", config.ErrBadRequest } params := ParamsToMap(FilterParams(toData.ServerParams, fileName, "", "", "location")) - return atscfg.MakeUnknownConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeUnknownConfig, nil + + commentType := atscfg.GetUnknownConfigCommentType(toData.Server.Profile, params, toData.TOToolName, toData.TOURL) + txt := atscfg.MakeUnknownConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL) + return txt, atscfg.ContentTypeUnknownConfig, commentType, nil } diff --git a/traffic_ops/ort/atstccfg/cfgfile/urisigningconfig.go b/traffic_ops/ort/atstccfg/cfgfile/urisigningconfig.go index 2136f51..8756b77 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/urisigningconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/urisigningconfig.go @@ -28,19 +28,19 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileURISigningConfig(toData *config.TOData, fileName string) (string, string, error) { +func GetConfigFileProfileURISigningConfig(toData *config.TOData, fileName string) (string, string, string, error) { dsName := GetDSFromURISigningConfigFileName(fileName) if dsName == "" { // extra safety, this should never happen, the routing shouldn't get here - return "", "", errors.New("getting ds name: malformed config file '" + fileName + "'") + return "", "", "", errors.New("getting ds name: malformed config file '" + fileName + "'") } uriSigningKeys, ok := toData.URISigningKeys[tc.DeliveryServiceName(dsName)] if !ok { - return "", "", errors.New("no keys fetched for ds '" + dsName + "!") + return "", "", "", errors.New("no keys fetched for ds '" + dsName + "!") } - return atscfg.MakeURISigningConfig(uriSigningKeys), atscfg.ContentTypeURISigningDotConfig, nil + return atscfg.MakeURISigningConfig(uriSigningKeys), atscfg.ContentTypeURISigningDotConfig, atscfg.LineCommentURISigningDotConfig, nil } // GetDSFromURISigningConfigFileName returns the DS of a URI Signing config file name. diff --git a/traffic_ops/ort/atstccfg/cfgfile/urlsigconfig.go b/traffic_ops/ort/atstccfg/cfgfile/urlsigconfig.go index f19a32d..eb689f2 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/urlsigconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/urlsigconfig.go @@ -28,31 +28,21 @@ import ( "github.com/apache/trafficcontrol/traffic_ops/ort/atstccfg/config" ) -func GetConfigFileProfileURLSigConfig(toData *config.TOData, fileName string) (string, string, error) { - paramData := map[string]string{} - // TODO add configFile query param to profile/parameters endpoint, to only get needed data - for _, param := range toData.ServerParams { - if param.ConfigFile != fileName { - continue - } - if param.Name == "location" { - continue - } - paramData[param.Name] = param.Value - } +func GetConfigFileProfileURLSigConfig(toData *config.TOData, fileName string) (string, string, string, error) { + paramData := ParamsToMap(FilterParams(toData.ServerParams, fileName, "", "", "location")) dsName := GetDSFromURLSigConfigFileName(fileName) if dsName == "" { // extra safety, this should never happen, the routing shouldn't get here - return "", "", errors.New("getting ds name: malformed config file '" + fileName + "'") + return "", "", "", errors.New("getting ds name: malformed config file '" + fileName + "'") } urlSigKeys, ok := toData.URLSigKeys[tc.DeliveryServiceName(dsName)] if !ok { - return "", "", errors.New("no keys fetched for ds '" + dsName + "!") + return "", "", "", errors.New("no keys fetched for ds '" + dsName + "!") } - return atscfg.MakeURLSigConfig(toData.Server.Profile, urlSigKeys, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeParentDotConfig, nil + return atscfg.MakeURLSigConfig(toData.Server.Profile, urlSigKeys, paramData, toData.TOToolName, toData.TOURL), atscfg.ContentTypeURLSig, atscfg.LineCommentURLSig, nil } // GetDSFromURLSigConfigFileName returns the DS of a URLSig config file name. diff --git a/traffic_ops/ort/atstccfg/cfgfile/volumedotconfig.go b/traffic_ops/ort/atstccfg/cfgfile/volumedotconfig.go index e5ad385..71f457d 100644 --- a/traffic_ops/ort/atstccfg/cfgfile/volumedotconfig.go +++ b/traffic_ops/ort/atstccfg/cfgfile/volumedotconfig.go @@ -26,7 +26,7 @@ import ( const VolumeFileName = StorageFileName -func GetConfigFileProfileVolumeDotConfig(toData *config.TOData) (string, string, error) { +func GetConfigFileProfileVolumeDotConfig(toData *config.TOData) (string, string, string, error) { params := ParamsToMap(FilterParams(toData.ServerParams, VolumeFileName, "", "", "")) - return atscfg.MakeVolumeDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeVolumeDotConfig, nil + return atscfg.MakeVolumeDotConfig(toData.Server.Profile, params, toData.TOToolName, toData.TOURL), atscfg.ContentTypeVolumeDotConfig, atscfg.LineCommentVolumeDotConfig, nil } diff --git a/traffic_ops/ort/atstccfg/config/config.go b/traffic_ops/ort/atstccfg/config/config.go index f8303cc..3b87f18 100644 --- a/traffic_ops/ort/atstccfg/config/config.go +++ b/traffic_ops/ort/atstccfg/config/config.go @@ -203,8 +203,21 @@ type ATSConfigFile struct { tc.ATSConfigMetaDataConfigFile Text string ContentType string + LineComment string } +// ATSConfigFiles implements sort.Interface and sorts by the Location and then FileNameOnDisk, i.e. the full file path. +type ATSConfigFiles []ATSConfigFile + +func (fs ATSConfigFiles) Len() int { return len(fs) } +func (fs ATSConfigFiles) Less(i, j int) bool { + if fs[i].Location != fs[j].Location { + return fs[i].Location < fs[j].Location + } + return fs[i].FileNameOnDisk < fs[j].FileNameOnDisk +} +func (fs ATSConfigFiles) Swap(i, j int) { fs[i], fs[j] = fs[j], fs[i] } + // TOData is the Traffic Ops data needed to generate configs. // See each field for details on the data required. // - If a field says 'must', the creation of TOData is guaranteed to do so, and users of the struct may rely on that. diff --git a/traffic_ops/ort/atstccfg/plugin/hello_world.go b/traffic_ops/ort/atstccfg/plugin/hello_world.go index f25fda9..0808692 100644 --- a/traffic_ops/ort/atstccfg/plugin/hello_world.go +++ b/traffic_ops/ort/atstccfg/plugin/hello_world.go @@ -41,6 +41,7 @@ func hello(d ModifyFilesData) []config.ATSConfigFile { fi.Text = "Hello, World!\n" fi.ContentType = "text/plain" + fi.LineComment = "" fi.FileNameOnDisk = "hello.txt" fi.Location = "/opt/trafficserver/etc/trafficserver/" diff --git a/traffic_ops/ort/atstccfg/plugin/plugin_test.go b/traffic_ops/ort/atstccfg/plugin/plugin_test.go index 68ffed3..2285876 100644 --- a/traffic_ops/ort/atstccfg/plugin/plugin_test.go +++ b/traffic_ops/ort/atstccfg/plugin/plugin_test.go @@ -34,6 +34,7 @@ func TestPlugin(t *testing.T) { fi := config.ATSConfigFile{} fi.Text = "testfile\n" fi.ContentType = "text/plain" + fi.LineComment = "" fi.FileNameOnDisk = "testfile.txt" fi.Location = "/opt/trafficserver/etc/trafficserver/" d.Files = append(d.Files, fi)