github.com/stakater/IngressMonitorController@v1.0.103/pkg/monitors/updown/updown-monitor.go (about)

     1  // Package UpdownMonitor adds updown website monitoring tool's support in IngressMonitorController
     2  package updown
     3  
     4  import (
     5  	"fmt"
     6  	"net/http"
     7  	"net/url"
     8  	"strconv"
     9  
    10  	log "github.com/sirupsen/logrus"
    11  
    12  	"github.com/antoineaugusti/updown"
    13  	"github.com/stakater/IngressMonitorController/pkg/config"
    14  	"github.com/stakater/IngressMonitorController/pkg/models"
    15  )
    16  
    17  const (
    18  	UpdownEnableCheckAnnotation = "updown.monitor.stakater.com/enable"
    19  	UpdownPeriodAnnotation      = "updown.monitor.stakater.com/period"
    20  	UpdownPublishPageAnnotation = "updown.monitor.stakater.com/publish-page"
    21  	// this annotation is not enabled
    22  	UpdownRequestHeadersAnnotation = "updown.monitor.stakater.com/request-headers"
    23  
    24  	// Default value for annotations
    25  	UpdownPeriodAnnotationDefaultValue    = 15
    26  	UpdownPublishedAnnotationDefaultValue = true
    27  	UpdownEnableAnnotationDefaultValue    = true
    28  )
    29  
    30  // UpdownMonitorService struct contains parameters required by updown go client
    31  type UpdownMonitorService struct {
    32  	apiKey string
    33  	client *updown.Client
    34  }
    35  
    36  // Setup method will initialize a updown's go client object by using the configuration parameters
    37  func (updownService *UpdownMonitorService) Setup(confProvider config.Provider) {
    38  
    39  	// initializeCustomLog(os.Stdout)
    40  	log.Println("Updown monitor's Setup has been called. Updown monitor initializing")
    41  
    42  	// updown go client apiKey
    43  	updownService.apiKey = confProvider.ApiKey
    44  
    45  	// creating updown go client
    46  	updownService.client = updown.NewClient(updownService.apiKey, http.DefaultClient)
    47  	log.Println("Updown monitor has been initialized")
    48  }
    49  
    50  // GetAll function will return all monitors (updown checks) object in an array
    51  func (updownService *UpdownMonitorService) GetAll() []models.Monitor {
    52  
    53  	log.Println("Updown monitor's GetAll method has been called")
    54  
    55  	var monitors []models.Monitor
    56  
    57  	// getting all monitors(checks) list
    58  	updownChecks, httpResponse, err := updownService.client.Check.List()
    59  	log.Println("Monitors (updown checks) object list has been pulled")
    60  
    61  	if (httpResponse.StatusCode == http.StatusOK) && (err == nil) {
    62  		log.Println("Populating monitors list using the updownChecks object given in updownChecks list")
    63  
    64  		// populating a monitors slice using the updownChecks objects given in updownChecks slice
    65  		for _, updownCheck := range updownChecks {
    66  			newMonitor := models.Monitor{
    67  				URL:  updownCheck.URL,
    68  				Name: updownCheck.Alias,
    69  				ID:   updownCheck.Token,
    70  			}
    71  			monitors = append(monitors, newMonitor)
    72  		}
    73  		return monitors
    74  
    75  	} else {
    76  		log.Println("Unable to get updown provider checks(monitor) list")
    77  		return nil
    78  
    79  	}
    80  
    81  }
    82  
    83  // GetByName function will return a monitor(updown check) object based on the name provided
    84  func (updownService *UpdownMonitorService) GetByName(monitorName string) (*models.Monitor, error) {
    85  
    86  	log.Println("Updown monitor's GetByName method has been called")
    87  
    88  	updownMonitors := updownService.GetAll()
    89  	log.Println("Monitors (updown checks) object list has been pulled")
    90  
    91  	log.Println("Searching the monitor from monitors object list using its name")
    92  	for _, updownMonitor := range updownMonitors {
    93  		if updownMonitor.Name == monitorName {
    94  			// Test the code below
    95  			return &updownMonitor, nil
    96  		}
    97  	}
    98  
    99  	return nil, fmt.Errorf("Unable to locate %v monitor", monitorName)
   100  }
   101  
   102  // Add function method will add a monitor (updown check)
   103  func (service *UpdownMonitorService) Add(updownMonitor models.Monitor) {
   104  
   105  	log.Println("Updown monitor's Add method has been called")
   106  
   107  	updownCheckItemObj := service.createHttpCheck(updownMonitor)
   108  
   109  	_, httpResponse, err := service.client.Check.Add(updownCheckItemObj)
   110  	log.Println("Monitor addition request has been completed")
   111  
   112  	if (httpResponse.StatusCode == http.StatusCreated) && (err == nil) {
   113  		log.Printf("Monitor %s has been added.", updownMonitor.Name)
   114  
   115  	} else if (httpResponse.StatusCode == http.StatusBadRequest) && (err != nil) {
   116  		log.Printf("Monitor %s is not created because of invalid parameters or it exists.", updownMonitor.Name)
   117  
   118  	} else {
   119  		log.Printf("Unable to create monitor %s ", updownMonitor.Name)
   120  
   121  	}
   122  
   123  }
   124  
   125  // createHttpCheck method it will populate updown CheckItem object using updownMonitor's attributes
   126  // and annotations
   127  func (updownService *UpdownMonitorService) createHttpCheck(updownMonitor models.Monitor) updown.CheckItem {
   128  
   129  	log.Println("Updown monitor's createHttpCheck method has been called")
   130  
   131  	// populating updownCheckItemObj object attributes using updownMonitor object
   132  	log.Println("Populating updownCheckItemObj object attributes using updownMonitor object")
   133  	updownCheckItemObj := updown.CheckItem{}
   134  
   135  	log.Println("Parsing URL")
   136  	_, err := url.Parse(updownMonitor.URL)
   137  
   138  	if err != nil {
   139  		log.Println("Unable to parse the URL : ", updownMonitor.URL)
   140  		return updownCheckItemObj
   141  	}
   142  
   143  	unEscapedURL, _ := url.QueryUnescape(updownMonitor.URL)
   144  	updownCheckItemObj.URL = unEscapedURL
   145  	updownCheckItemObj.Alias = updownMonitor.Name
   146  
   147  	// populating updownCheckItemObj object attributes using
   148  	log.Println("Populating updownCheckItemObj object attributes using annotations")
   149  	updownService.addAnnotationConfigToHttpCheck(&updownCheckItemObj, updownMonitor.Annotations)
   150  
   151  	return updownCheckItemObj
   152  }
   153  
   154  // addAnnotationConfigToHttpCheck method will populate Updown's CheckItem object attributes using the annotations map
   155  func (service *UpdownMonitorService) addAnnotationConfigToHttpCheck(updownCheckItemObj *updown.CheckItem, annotations map[string]string) {
   156  	// Read known annotations, try to map them to updown check configs
   157  	// set some default values if we can't find them
   158  
   159  	log.Println("Updown monitor's addAnnotationConfigToHttpCheck method has been called")
   160  
   161  	// Enable Annotation
   162  	if value, ok := annotations[UpdownEnableCheckAnnotation]; ok {
   163  		boolValue, err := strconv.ParseBool(value)
   164  
   165  		if err == nil {
   166  			updownCheckItemObj.Enabled = boolValue
   167  
   168  		} else {
   169  			log.Println("Error decoding input into an boolean")
   170  			updownCheckItemObj.Enabled = UpdownEnableAnnotationDefaultValue
   171  
   172  		}
   173  	}
   174  
   175  	// Published Annotation
   176  	if value, ok := annotations[UpdownPublishPageAnnotation]; ok {
   177  		boolValue, err := strconv.ParseBool(value)
   178  
   179  		if err == nil {
   180  			updownCheckItemObj.Published = boolValue
   181  
   182  		} else {
   183  			log.Println("Error decoding input into an boolean")
   184  			updownCheckItemObj.Published = UpdownPublishedAnnotationDefaultValue
   185  
   186  		}
   187  	}
   188  
   189  	// Period Annotation
   190  	if value, ok := annotations[UpdownPeriodAnnotation]; ok {
   191  		intValue, err := strconv.Atoi(value)
   192  
   193  		if err == nil {
   194  			updownCheckItemObj.Period = intValue
   195  
   196  		} else {
   197  			log.Println("Error decoding input into an integer")
   198  			updownCheckItemObj.Period = UpdownPeriodAnnotationDefaultValue
   199  
   200  		}
   201  
   202  	} else {
   203  		updownCheckItemObj.Period = UpdownPeriodAnnotationDefaultValue
   204  
   205  	}
   206  
   207  }
   208  
   209  // Update method will update a monitor (updown check)
   210  func (service *UpdownMonitorService) Update(updownMonitor models.Monitor) {
   211  
   212  	log.Println("Updown's Update method has been called")
   213  
   214  	httpCheckItemObj := service.createHttpCheck(updownMonitor)
   215  	_, httpResponse, err := service.client.Check.Update(updownMonitor.ID, httpCheckItemObj)
   216  	log.Println("Updown's check Update request has been completed")
   217  
   218  	if (httpResponse.StatusCode == http.StatusOK) && (err == nil) {
   219  		log.Printf("Monitor %s has been updated with following parameters", updownMonitor.Name)
   220  
   221  	} else {
   222  		log.Printf("Monitor %s is not updated because of %s", updownMonitor.Name, err.Error())
   223  
   224  	}
   225  
   226  }
   227  
   228  // Remove method will remove a monitor (updown check)
   229  func (updownService *UpdownMonitorService) Remove(updownMonitor models.Monitor) {
   230  
   231  	log.Println("Updown's Remove method has been called")
   232  
   233  	_, httpResponse, err := updownService.client.Check.Remove(updownMonitor.ID)
   234  	log.Println("Updown's check Remove request has been completed")
   235  
   236  	if (httpResponse.StatusCode == http.StatusOK) && (err == nil) {
   237  		log.Printf("Monitor %v has been deleted.", updownMonitor.Name)
   238  
   239  	} else if (httpResponse.StatusCode == http.StatusNotFound) && (err != nil) {
   240  		log.Printf("Monitor %v is not found.", updownMonitor.Name)
   241  
   242  	} else {
   243  		log.Printf("Unable to delete %v monitor: ", updownMonitor.Name)
   244  	}
   245  
   246  }