github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/config-migrate.go (about) 1 // Copyright (c) 2015-2021 MinIO, Inc. 2 // 3 // This file is part of MinIO Object Storage stack 4 // 5 // This program is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Affero General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // This program is distributed in the hope that it will be useful 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Affero General Public License for more details. 14 // 15 // You should have received a copy of the GNU Affero General Public License 16 // along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 package cmd 19 20 import ( 21 "context" 22 "encoding/json" 23 "errors" 24 "path" 25 "strings" 26 27 "github.com/minio/minio/internal/config" 28 "github.com/minio/minio/internal/config/compress" 29 xldap "github.com/minio/minio/internal/config/identity/ldap" 30 "github.com/minio/minio/internal/config/identity/openid" 31 "github.com/minio/minio/internal/config/notify" 32 "github.com/minio/minio/internal/config/policy/opa" 33 "github.com/minio/minio/internal/config/storageclass" 34 "github.com/minio/minio/internal/event/target" 35 "github.com/minio/minio/internal/logger" 36 xnet "github.com/minio/pkg/v2/net" 37 "github.com/minio/pkg/v2/quick" 38 ) 39 40 // Save config file to corresponding backend 41 func Save(configFile string, data interface{}) error { 42 return quick.SaveConfig(data, configFile, globalEtcdClient) 43 } 44 45 // Load config from backend 46 func Load(configFile string, data interface{}) (quick.Config, error) { 47 return quick.LoadConfig(configFile, globalEtcdClient, data) 48 } 49 50 func readConfigWithoutMigrate(ctx context.Context, objAPI ObjectLayer) (config.Config, error) { 51 // Construct path to config.json for the given bucket. 52 configFile := path.Join(minioConfigPrefix, minioConfigFile) 53 54 configFiles := []string{ 55 getConfigFile(), 56 getConfigFile() + ".deprecated", 57 configFile, 58 } 59 60 newServerCfg := func() (config.Config, error) { 61 // Initialize server config. 62 srvCfg := newServerConfig() 63 64 return srvCfg, saveServerConfig(ctx, objAPI, srvCfg) 65 } 66 67 var data []byte 68 var err error 69 70 cfg := &serverConfigV33{} 71 for _, cfgFile := range configFiles { 72 if _, err = Load(cfgFile, cfg); err != nil { 73 if !osIsNotExist(err) && !osIsPermission(err) { 74 return nil, err 75 } 76 continue 77 } 78 data, _ = json.Marshal(cfg) 79 break 80 } 81 if osIsPermission(err) { 82 logger.Info("Older config found but is not readable %s, proceeding to read config from other places", err) 83 } 84 if osIsNotExist(err) || osIsPermission(err) || len(data) == 0 { 85 data, err = readConfig(GlobalContext, objAPI, configFile) 86 if err != nil { 87 // when config.json is not found, then we freshly initialize. 88 if errors.Is(err, errConfigNotFound) { 89 return newServerCfg() 90 } 91 return nil, err 92 } 93 94 data, err = decryptData(data, configFile) 95 if err != nil { 96 return nil, err 97 } 98 99 newCfg, err := readServerConfig(GlobalContext, objAPI, data) 100 if err == nil { 101 return newCfg, nil 102 } 103 104 // Read older `.minio.sys/config/config.json`, if not 105 // possible just fail. 106 if err = json.Unmarshal(data, cfg); err != nil { 107 // Unable to parse old JSON simply re-initialize a new one. 108 return newServerCfg() 109 } 110 } 111 112 if !globalCredViaEnv && cfg.Credential.IsValid() { 113 // Preserve older credential if we do not have 114 // root credentials set via environment variable. 115 globalActiveCred = cfg.Credential 116 } 117 118 // Init compression config. For future migration, Compression config needs to be copied over from previous version. 119 switch cfg.Version { 120 case "29": 121 // V29 -> V30 122 cfg.Compression.Enabled = false 123 cfg.Compression.Extensions = strings.Split(compress.DefaultExtensions, config.ValueSeparator) 124 cfg.Compression.MimeTypes = strings.Split(compress.DefaultMimeTypes, config.ValueSeparator) 125 case "30": 126 // V30 -> V31 127 cfg.OpenID = openid.Config{} 128 cfg.Policy.OPA = opa.Args{ 129 URL: &xnet.URL{}, 130 AuthToken: "", 131 } 132 case "31": 133 // V31 -> V32 134 cfg.Notify.NSQ = make(map[string]target.NSQArgs) 135 cfg.Notify.NSQ["1"] = target.NSQArgs{} 136 } 137 138 // Move to latest. 139 cfg.Version = "33" 140 141 newCfg := newServerConfig() 142 143 config.SetRegion(newCfg, cfg.Region) 144 storageclass.SetStorageClass(newCfg, cfg.StorageClass) 145 146 for k, loggerArgs := range cfg.Logger.HTTP { 147 logger.SetLoggerHTTP(newCfg, k, loggerArgs) 148 } 149 for k, auditArgs := range cfg.Logger.AuditWebhook { 150 logger.SetLoggerHTTPAudit(newCfg, k, auditArgs) 151 } 152 153 xldap.SetIdentityLDAP(newCfg, cfg.LDAPServerConfig) 154 opa.SetPolicyOPAConfig(newCfg, cfg.Policy.OPA) 155 compress.SetCompressionConfig(newCfg, cfg.Compression) 156 157 for k, args := range cfg.Notify.AMQP { 158 notify.SetNotifyAMQP(newCfg, k, args) 159 } 160 for k, args := range cfg.Notify.Elasticsearch { 161 notify.SetNotifyES(newCfg, k, args) 162 } 163 for k, args := range cfg.Notify.Kafka { 164 notify.SetNotifyKafka(newCfg, k, args) 165 } 166 for k, args := range cfg.Notify.MQTT { 167 notify.SetNotifyMQTT(newCfg, k, args) 168 } 169 for k, args := range cfg.Notify.MySQL { 170 notify.SetNotifyMySQL(newCfg, k, args) 171 } 172 for k, args := range cfg.Notify.NATS { 173 notify.SetNotifyNATS(newCfg, k, args) 174 } 175 for k, args := range cfg.Notify.NSQ { 176 notify.SetNotifyNSQ(newCfg, k, args) 177 } 178 for k, args := range cfg.Notify.PostgreSQL { 179 notify.SetNotifyPostgres(newCfg, k, args) 180 } 181 for k, args := range cfg.Notify.Redis { 182 notify.SetNotifyRedis(newCfg, k, args) 183 } 184 for k, args := range cfg.Notify.Webhook { 185 notify.SetNotifyWebhook(newCfg, k, args) 186 } 187 188 return newCfg, nil 189 }