blob: 804c0e704a6a751c95789c311f27f949e8c0b9d9 [file] [log] [blame]
package atscfg
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import (
"encoding/json"
"strings"
"github.com/apache/trafficcontrol/lib/go-log"
"github.com/apache/trafficcontrol/lib/go-tc"
)
type ConfigProfileParams struct {
FileNameOnDisk string
Location string
URL string
APIURI string
}
// APIVersion is the Traffic Ops API version for config fiels.
// This is used to generate the meta config, which has API paths.
// Note the version in the meta config is not used by the atstccfg generator, which isn't actually an API.
// TODO change the config system to not use old API paths, and remove this.
const APIVersion = "1.4"
func MakeMetaConfig(
serverHostName tc.CacheName,
server *ServerInfo,
tmURL string, // global tm.url Parameter
tmReverseProxyURL string, // global tm.rev_proxy.url Parameter
locationParams map[string]ConfigProfileParams, // map[configFile]params; 'location' and 'URL' Parameters on serverHostName's Profile
uriSignedDSes []tc.DeliveryServiceName,
scopeParams map[string]string, // map[configFileName]scopeParam
dsNames map[tc.DeliveryServiceName]struct{},
) string {
if tmURL == "" {
log.Errorln("ats.GetConfigMetadata: global tm.url parameter missing or empty! Setting empty in meta config!")
}
atsData := tc.ATSConfigMetaData{
Info: tc.ATSConfigMetaDataInfo{
ProfileID: int(server.ProfileID),
TOReverseProxyURL: tmReverseProxyURL,
TOURL: tmURL,
ServerIPv4: server.IP,
ServerPort: server.Port,
ServerName: server.HostName,
CDNID: server.CDNID,
CDNName: string(server.CDN),
ServerID: server.ID,
ProfileName: server.ProfileName,
},
ConfigFiles: []tc.ATSConfigMetaDataConfigFile{},
}
if locationParams["remap.config"].Location != "" {
configLocation := locationParams["remap.config"].Location
for _, ds := range uriSignedDSes {
cfgName := "uri_signing_" + string(ds) + ".config"
// If there's already a parameter for it, don't clobber it. The user may wish to override the location.
if _, ok := locationParams[cfgName]; !ok {
p := locationParams[cfgName]
p.FileNameOnDisk = cfgName
p.Location = configLocation
locationParams[cfgName] = p
}
}
}
locationParamsFor:
for cfgFile, cfgParams := range locationParams {
if strings.HasSuffix(cfgFile, ".config") {
dsConfigFilePrefixes := []string{
"hdr_rw_mid_", // must come before hdr_rw_, to avoid thinking we have a "hdr_rw_" with a ds of "mid_x"
"hdr_rw_",
"regex_remap_",
"url_sig_",
"uri_signing_",
}
prefixFor:
for _, prefix := range dsConfigFilePrefixes {
if strings.HasPrefix(cfgFile, prefix) {
dsName := strings.TrimSuffix(strings.TrimPrefix(cfgFile, prefix), ".config")
if _, ok := dsNames[tc.DeliveryServiceName(dsName)]; !ok {
log.Warnln("Server Profile had 'location' Parameter '" + cfgFile + "', but delivery Service '" + dsName + "' is not assigned to this Server! Not including in meta config!")
continue locationParamsFor
}
break prefixFor // if it has a prefix, don't check the next prefix. This is important for hdr_rw_mid_, which will match hdr_rw_ and result in a "ds name" of "mid_x" if we don't continue here.
}
}
}
atsCfg := tc.ATSConfigMetaDataConfigFile{
FileNameOnDisk: cfgParams.FileNameOnDisk,
Location: cfgParams.Location,
}
scope := getServerScope(cfgFile, server.Type, scopeParams)
if cfgParams.URL != "" {
scope = tc.ATSConfigMetaDataConfigFileScopeCDNs
atsCfg.URL = cfgParams.URL
} else {
scopeID := ""
if scope == tc.ATSConfigMetaDataConfigFileScopeCDNs {
scopeID = string(server.CDN)
} else if scope == tc.ATSConfigMetaDataConfigFileScopeProfiles {
scopeID = server.ProfileName
} else { // ATSConfigMetaDataConfigFileScopeServers
scopeID = server.HostName
}
atsCfg.APIURI = "/api/" + APIVersion + "/" + string(scope) + "/" + scopeID + "/configfiles/ats/" + cfgFile
}
atsCfg.Scope = string(scope)
atsData.ConfigFiles = append(atsData.ConfigFiles, atsCfg)
}
bts, err := json.Marshal(atsData)
if err != nil {
// should never happen
log.Errorln("marshalling chkconfig NameVersions: " + err.Error())
bts = []byte("error encoding to json, see log for details")
}
return string(bts)
}
func getServerScope(cfgFile string, serverType string, scopeParams map[string]string) tc.ATSConfigMetaDataConfigFileScope {
switch {
case cfgFile == "cache.config" && tc.CacheTypeFromString(serverType) == tc.CacheTypeMid:
return tc.ATSConfigMetaDataConfigFileScopeServers
default:
return getScope(cfgFile, scopeParams)
}
}
const DefaultScope = tc.ATSConfigMetaDataConfigFileScopeServers
// getScope returns the ATSConfigMetaDataConfigFileScope for the given config file, and potentially the given server. If the config is not a Server scope, i.e. was part of an endpoint which does not include a server name or id, the server may be nil.
func getScope(cfgFile string, scopeParams map[string]string) tc.ATSConfigMetaDataConfigFileScope {
switch {
case cfgFile == "ip_allow.config",
cfgFile == "parent.config",
cfgFile == "hosting.config",
cfgFile == "packages",
cfgFile == "chkconfig",
cfgFile == "remap.config",
strings.HasPrefix(cfgFile, "to_ext_") && strings.HasSuffix(cfgFile, ".config"):
return tc.ATSConfigMetaDataConfigFileScopeServers
case cfgFile == "12M_facts",
cfgFile == "50-ats.rules",
cfgFile == "astats.config",
cfgFile == "cache.config",
cfgFile == "drop_qstring.config",
cfgFile == "logs_xml.config",
cfgFile == "logging.config",
cfgFile == "plugin.config",
cfgFile == "records.config",
cfgFile == "storage.config",
cfgFile == "volume.config",
cfgFile == "sysctl.conf",
strings.HasPrefix(cfgFile, "url_sig_") && strings.HasSuffix(cfgFile, ".config"),
strings.HasPrefix(cfgFile, "uri_signing_") && strings.HasSuffix(cfgFile, ".config"):
return tc.ATSConfigMetaDataConfigFileScopeProfiles
case cfgFile == "bg_fetch.config",
cfgFile == "regex_revalidate.config",
cfgFile == "ssl_multicert.config",
strings.HasPrefix(cfgFile, "cacheurl") && strings.HasSuffix(cfgFile, ".config"),
strings.HasPrefix(cfgFile, "hdr_rw_") && strings.HasSuffix(cfgFile, ".config"),
strings.HasPrefix(cfgFile, "regex_remap_") && strings.HasSuffix(cfgFile, ".config"),
strings.HasPrefix(cfgFile, "set_dscp_") && strings.HasSuffix(cfgFile, ".config"):
return tc.ATSConfigMetaDataConfigFileScopeCDNs
}
scope, ok := scopeParams[cfgFile]
if !ok {
scope = string(DefaultScope)
}
return tc.ATSConfigMetaDataConfigFileScope(scope)
}