github.com/stakater/IngressMonitorController@v1.0.103/CONTRIBUTING.md (about)

     1  # Contributing
     2  
     3  ## Workflow
     4  Pull Requests are welcome. In general, we follow the "fork-and-pull" Git workflow.
     5  
     6   1. **Fork** the repo on GitHub
     7   2. **Clone** the project to your own machine
     8   3. **Commit** changes to your own branch
     9   4. **Push** your work back up to your fork
    10   5. Submit a **Pull request** so that we can review your changes
    11  
    12  NOTE: Be sure to merge the latest from "upstream" before making a pull request!
    13  
    14  ## Golang code practice
    15  
    16  Follow this [tour](https://tour.golang.org/) to practice golang.
    17  
    18  # Extending Ingress Monitor Controller
    19  
    20  ## Adding support for a new Monitor
    21  
    22  You can easily implement a new monitor and use it via the controller. First of all you will need to create a folder under `/pkg/monitors/` with the name of the new monitor and then you will create a new service struct inside this folder that implements the following monitor service interface
    23  
    24  ```go
    25  type MonitorService interface {
    26      GetAll() []Monitor
    27      Add(m Monitor)
    28      Update(m Monitor)
    29      GetByName(name string) (*Monitor, error)
    30      Remove(m Monitor)
    31      Setup(provider Provider)
    32  }
    33  ```
    34  
    35  *Note:* While developing, make sure to follow the conventions mentioned below in the [Naming Conventions section](#naming-conventions)
    36  
    37  Once the implementation of your service is done, you have to open up `monitor-proxy.go` and add a new case inside `OfType` method for your new monitor. Lets say you have named your service `MyNewMonitorService`, then you have to add the case like in the example below:
    38  
    39  ```go
    40  func (mp *MonitorServiceProxy) OfType(mType string) MonitorServiceProxy {
    41      mp.monitorType = mType
    42      switch mType {
    43      case "UptimeRobot":
    44          mp.monitor = &UpTimeMonitorService{}
    45      case "MyNewMonitor":
    46          mp.monitor = &MyNewMonitorService{}
    47      default:
    48          log.Panic("No such provider found")
    49      }
    50      return *mp
    51  }
    52  ```
    53  
    54  Note that the name you specify here for the case will be the key for your new monitor which you can add it in ConfigMap.
    55  
    56  Also in case of handling custom api objects for the monitor api, you can create mappers that map from the api objects to the generic `Monitor` objects. The way you have to create these is to create a file named `monitorname-mappers.go` and add mapping functions in that file. An example of a mapping function is found below:
    57  
    58  ```go
    59  func UptimeMonitorMonitorToBaseMonitorMapper(uptimeMonitor UptimeMonitorMonitor) *Monitor {
    60      var m Monitor
    61  
    62      m.name = uptimeMonitor.FriendlyName
    63      m.url = uptimeMonitor.URL
    64      m.id = strconv.Itoa(uptimeMonitor.ID)
    65  
    66      return &m
    67  }
    68  ```
    69  
    70  ## Naming Conventions
    71  
    72  ### Annotations
    73  
    74  You should use the following format for annotations when there are monitor specific annotations:
    75  
    76  ```bash
    77  <monitor-name>.monitor.stakater.com/<annotation-name>
    78  ```
    79  
    80  You should use the following format for annotations when there are global annotations:
    81  
    82  ```bash
    83  monitor.stakater.com/<annotation-name>
    84  ```
    85  
    86  #### Examples
    87  
    88  For example you're adding support for a new monitor service named `alertme`, it's specific annotations would look like the following:
    89  
    90  ```bash
    91  alertme.monitor.stakater.com/some-key
    92  ```
    93  
    94  In case of a global annotation, lets say you want to create 1 for disabling deletion of specific monitors, it would look like so:
    95  
    96  ```bash
    97  monitor.stakater.com/keep-on-delete
    98  ```
    99  
   100  # Testing
   101  
   102  ## Running Tests Locally
   103  
   104  Tests require a Kubernetes instance to talk to with a `test` namespace created, and a config with a valid UptimeRobot `apiKey` and `alertContacts`. For example, on MacOS with Homebrew and Minikube, you could accomplish this like
   105  
   106  ```bash
   107  # while still in the root folder, configure test setup
   108  $ export CONFIG_FILE_PATH=$(pwd)/configs/testConfigs/test-config.yaml
   109  # update the apikey and alertContacts in this file and the config_test.go file (`correctTestAPIKey` and `correctTestAlertContacts` contstants)
   110  $ minikube start
   111  $ kubectl create namespace test
   112  
   113  # run the following command in the root folder
   114  $ make test
   115  ```
   116  
   117  ## Test config for monitors
   118  
   119  When running monitor test cases, make sure to provide a config similar to the following:
   120  ```yaml
   121  providers:
   122    - name: UptimeRobot
   123      apiKey: <your-api-key>
   124      apiURL: https://api.uptimerobot.com/v2/
   125      alertContacts: <your-alert-contacts>
   126    - name: StatusCake
   127      apiKey: <your-api-key>
   128      apiURL: https://app.statuscake.com/API/
   129      username: <your-account-username>
   130      password: <your-account-password>
   131    - name: Pingdom
   132      apiKey: <your-api-key>
   133      apiURL: https://api.pingdom.com
   134      username: <your-account-username>
   135      password: <your-account-password>
   136      accountEmail: <multi-auth-account-email>
   137  enableMonitorDeletion: true
   138  monitorNameTemplate: "{{.IngressName}}-{{.Namespace}}"
   139  ```