| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Minio Cloud Storage, (C) 2016 Minio, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-19 07:23:42 +08:00
										 |  |  | package cmd | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/Sirupsen/logrus" | 
					
						
							|  |  |  | 	"github.com/minio/redigo/redis" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | // redisNotify to send logs to Redis server
 | 
					
						
							|  |  |  | type redisNotify struct { | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	Enable   bool   `json:"enable"` | 
					
						
							|  |  |  | 	Addr     string `json:"address"` | 
					
						
							|  |  |  | 	Password string `json:"password"` | 
					
						
							|  |  |  | 	Key      string `json:"key"` | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type redisConn struct { | 
					
						
							|  |  |  | 	*redis.Pool | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	params redisNotify | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-04 08:29:55 +08:00
										 |  |  | // Dial a new connection to redis instance at addr, optionally with a
 | 
					
						
							|  |  |  | // password if any.
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | func dialRedis(rNotify redisNotify) (*redis.Pool, error) { | 
					
						
							| 
									
										
										
										
											2016-07-26 08:53:55 +08:00
										 |  |  | 	// Return error if redis not enabled.
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	if !rNotify.Enable { | 
					
						
							|  |  |  | 		return nil, errNotifyNotEnabled | 
					
						
							| 
									
										
										
										
											2016-07-26 08:53:55 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	addr := rNotify.Addr | 
					
						
							|  |  |  | 	password := rNotify.Password | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	rPool := &redis.Pool{ | 
					
						
							|  |  |  | 		MaxIdle:     3, | 
					
						
							| 
									
										
										
										
											2016-09-20 17:11:17 +08:00
										 |  |  | 		IdleTimeout: 240 * time.Second, // Time 2minutes.
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 		Dial: func() (redis.Conn, error) { | 
					
						
							|  |  |  | 			c, err := redis.Dial("tcp", addr) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if password != "" { | 
					
						
							| 
									
										
										
										
											2016-07-26 11:36:56 +08:00
										 |  |  | 				if _, derr := c.Do("AUTH", password); derr != nil { | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 					c.Close() | 
					
						
							| 
									
										
										
										
											2016-07-26 11:36:56 +08:00
										 |  |  | 					return nil, derr | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return c, err | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		TestOnBorrow: func(c redis.Conn, t time.Time) error { | 
					
						
							|  |  |  | 			_, err := c.Do("PING") | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Test if connection with REDIS can be established.
 | 
					
						
							|  |  |  | 	rConn := rPool.Get() | 
					
						
							|  |  |  | 	defer rConn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check connection.
 | 
					
						
							|  |  |  | 	_, err := rConn.Do("PING") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Return pool.
 | 
					
						
							|  |  |  | 	return rPool, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | func newRedisNotify(accountID string) (*logrus.Logger, error) { | 
					
						
							|  |  |  | 	rNotify := serverConfig.GetRedisNotifyByID(accountID) | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Dial redis.
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	rPool, err := dialRedis(rNotify) | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rrConn := redisConn{ | 
					
						
							|  |  |  | 		Pool:   rPool, | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 		params: rNotify, | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	redisLog := logrus.New() | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	redisLog.Out = ioutil.Discard | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Set default JSON formatter.
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	redisLog.Formatter = new(logrus.JSONFormatter) | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	redisLog.Hooks.Add(rrConn) | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | 	// Success, redis enabled.
 | 
					
						
							|  |  |  | 	return redisLog, nil | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-05 13:01:58 +08:00
										 |  |  | // Fire is called when an event should be sent to the message broker.
 | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | func (r redisConn) Fire(entry *logrus.Entry) error { | 
					
						
							|  |  |  | 	rConn := r.Pool.Get() | 
					
						
							|  |  |  | 	defer rConn.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:11:17 +08:00
										 |  |  | 	// Fetch event type upon reflecting on its original type.
 | 
					
						
							|  |  |  | 	entryStr, ok := entry.Data["EventType"].(string) | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		return nil | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:11:17 +08:00
										 |  |  | 	// Match the event if its a delete request, attempt to delete the key
 | 
					
						
							|  |  |  | 	if eventMatch(entryStr, []string{"s3:ObjectRemoved:*"}) { | 
					
						
							|  |  |  | 		if _, err := rConn.Do("DEL", entry.Data["Key"]); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} // else save this as new entry or update any existing ones.
 | 
					
						
							|  |  |  | 	if _, err := rConn.Do("SET", entry.Data["Key"], map[string]interface{}{ | 
					
						
							|  |  |  | 		"Records": entry.Data["Records"], | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							| 
									
										
										
										
											2016-07-24 13:51:12 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Required for logrus hook implementation
 | 
					
						
							|  |  |  | func (r redisConn) Levels() []logrus.Level { | 
					
						
							|  |  |  | 	return []logrus.Level{ | 
					
						
							|  |  |  | 		logrus.InfoLevel, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |