diff --git a/lib/go-atscfg/astatsdotconfig.go b/lib/go-atscfg/astatsdotconfig.go index 0fbc0bff96..8ea62d5755 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 2e38e4ea11..8798ed37e4 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 5ea8f437f8..286d44edd2 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 348061353a..7629e40a8a 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 ba95e0e234..7b23107df7 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 f6a077c53d..1f48110f21 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 581ca38000..9d870c90b2 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 3c7c59bd5e..68d91897f5 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 70102ce2ad..c7e6eb61ba 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 083ee91080..34a96aeb14 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 f3f53bc79c..5df86e9acb 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 74b27c13fa..d2a1744f5c 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 fdb24fcc62..0d9f375275 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 02e39683b7..72ccd66dba 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 991b41186d..72e6525ef9 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 = `