SHARE
TWEET

Untitled

a guest Jan 19th, 2020 77 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package main
  2.  
  3. import (
  4.   "flag"
  5.   "fmt"
  6.   "syscall"
  7.   "os"
  8.   "io/ioutil"
  9.   "strconv"
  10.   "os/user"
  11.   "database/sql"
  12.  
  13.   _ "github.com/go-sql-driver/mysql"
  14.   "gopkg.in/yaml.v2"
  15. )
  16.  
  17. // DbCredentials represents MySQL credentials. It is also part of yaml config`
  18. type DbCredentials struct {
  19.     Driver      string
  20.     User        string
  21.     Pass        string
  22.     Port        int
  23.     Host        string
  24.     Name        string
  25. }
  26.  
  27. // Index is part of yaml configuration
  28. type Index struct {
  29.     MinSize     int         `yaml:"min_size"`
  30.     IndexSum    []string    `yaml:"index_sum"`
  31. }
  32.  
  33. // Config is a root structure of yaml of config
  34. type Config struct {
  35.     Parameters  DbCredentials
  36.     Indexes     map[string]Index
  37.     SphinxUser  string              `yaml:"sphinx_user"`
  38.     SphinxGroup string              `yaml:"sphinx_group"`
  39.     Files       []string
  40. }
  41.  
  42. func dbConnection(credentials *DbCredentials) (db *sql.DB) {
  43.     dns := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", credentials.User, credentials.Pass, credentials.Host, credentials.Port, credentials.Name)
  44.     db, err := sql.Open("mysql", dns)
  45.  
  46.     if err != nil {
  47.         panic(err.Error())
  48.     }
  49.  
  50.     return db
  51. }
  52.  
  53. func parseConfig(configPath string) Config {
  54.     configData, err := ioutil.ReadFile(configPath)
  55.     if err != nil {
  56.         panic("Cannot read config file from "+configPath)
  57.     }
  58.    
  59.     conf := Config{}
  60.     if err = yaml.Unmarshal([]byte(configData), &conf); err != nil {
  61.         panic(err)
  62.     }
  63.  
  64.     return conf
  65. }
  66.  
  67. func countIndex(db *sql.DB, name string) int {
  68.     rows, err := db.Query("SELECT COUNT(*) FROM "+name)
  69.     if err != nil {
  70.         panic(err)
  71.     }
  72.     defer rows.Close();
  73.  
  74.     for rows.Next() {
  75.         var num int
  76.         if err := rows.Scan(&num); err != nil {
  77.             panic(err)
  78.         }
  79.        
  80.         return num
  81.     }
  82.  
  83.     panic("Index not found")
  84. }
  85.  
  86. func checkIndexes(db *sql.DB, indexes *map[string]Index) {
  87.     count := map[string]int{}
  88.  
  89.     for k, v := range *indexes {
  90.         count[k] = countIndex(db, k)
  91.         if v.MinSize > 0 && count[k] < v.MinSize {
  92.             panic(fmt.Sprintf("Index %s is too small. Expected size: atleast %d. Given %d",
  93.                 k, v.MinSize, count[k]))
  94.         }
  95.     }
  96.  
  97.     var sum int
  98.     for k, v := range *indexes {
  99.         if len(v.IndexSum) <= 0 {
  100.             continue
  101.         }
  102.         sum = 0
  103.  
  104.         for _, item := range v.IndexSum {
  105.             if val, ok := count[item]; ok {
  106.                 sum += val
  107.                 continue
  108.             }
  109.  
  110.             panic(fmt.Sprintf("Index %s required to compute sum for %s is not defined.",
  111.                 item, k))
  112.         }
  113.  
  114.         if sum != count[k] {
  115.             panic(fmt.Sprintf("Sum for index %s is invalid", k))
  116.         }
  117.     }
  118. }
  119.  
  120. func getFileOwner(filePath string) (string, string){
  121.     info, err := os.Stat(filePath)
  122.  
  123.     if err != nil {
  124.         panic(fmt.Sprintf("Cannot read %s", filePath))
  125.     }
  126.  
  127.     var UID, GID string
  128.     if stat, ok := info.Sys().(*syscall.Stat_t); ok {
  129.         UID = strconv.Itoa(int(stat.Uid))
  130.         GID = strconv.Itoa(int(stat.Gid))
  131.     } else {
  132.         UID = "0"
  133.         GID = "0"
  134.     }
  135.  
  136.     return UID, GID
  137. }
  138.  
  139. func checkFiles(username string, group string, files []string) {
  140.     givenGroup, gErr := user.LookupGroup(group)
  141.     if gErr != nil {
  142.         panic(fmt.Sprintf("Group %s does not exist", group))
  143.     }
  144.  
  145.     givenUser, uErr := user.Lookup(username)
  146.     if uErr != nil {
  147.         panic(fmt.Sprintf("User %s does not exist", username))
  148.     }
  149.  
  150.     var fileUID, fileGID string
  151.     for _, file := range files {
  152.         fileUID, fileGID = getFileOwner(file)
  153.         if [2]interface{}{givenUser.Uid, givenGroup.Gid} != [2]interface{}{fileUID, fileGID} {
  154.             panic(fmt.Sprintf("Owner or Group of the file %s is incorrect.", file))
  155.         }
  156.     }
  157. }
  158.  
  159. func main() {
  160.     var configPath string
  161.    
  162.     flag.StringVar(&configPath, "config", "/etc/sphinx-health-check.yml", "Path to configuration file")
  163.     flag.Parse()
  164.  
  165.     config := parseConfig(configPath)
  166.     var db *sql.DB = dbConnection(&config.Parameters)
  167.     defer db.Close()
  168.  
  169.    
  170.    
  171.     checkIndexes(db, &config.Indexes)
  172.     checkFiles(config.SphinxUser, config.SphinxUser, config.Files)
  173.  
  174.     fmt.Println("Sphinx is working")
  175. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top