github.com/bndr/gojenkins@v1.1.0/node.go (about) 1 // Copyright 2015 Vadim Kravcenko 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package gojenkins 16 17 import ( 18 "context" 19 "errors" 20 ) 21 22 // Nodes 23 24 type Computers struct { 25 BusyExecutors int `json:"busyExecutors"` 26 Computers []*NodeResponse `json:"computer"` 27 DisplayName string `json:"displayName"` 28 TotalExecutors int `json:"totalExecutors"` 29 } 30 31 type Node struct { 32 Raw *NodeResponse 33 Jenkins *Jenkins 34 Base string 35 } 36 37 type NodeResponse struct { 38 Class string `json:"_class"` 39 Actions []interface{} `json:"actions"` 40 DisplayName string `json:"displayName"` 41 Executors []struct { 42 CurrentExecutable struct { 43 Number int `json:"number"` 44 URL string `json:"url"` 45 SubBuilds []struct { 46 Abort bool `json:"abort"` 47 Build interface{} `json:"build"` 48 BuildNumber int `json:"buildNumber"` 49 Duration string `json:"duration"` 50 Icon string `json:"icon"` 51 JobName string `json:"jobName"` 52 ParentBuildNumber int `json:"parentBuildNumber"` 53 ParentJobName string `json:"parentJobName"` 54 PhaseName string `json:"phaseName"` 55 Result string `json:"result"` 56 Retry bool `json:"retry"` 57 URL string `json:"url"` 58 } `json:"subBuilds"` 59 } `json:"currentExecutable"` 60 } `json:"executors"` 61 Icon string `json:"icon"` 62 IconClassName string `json:"iconClassName"` 63 Idle bool `json:"idle"` 64 JnlpAgent bool `json:"jnlpAgent"` 65 LaunchSupported bool `json:"launchSupported"` 66 LoadStatistics struct{} `json:"loadStatistics"` 67 ManualLaunchAllowed bool `json:"manualLaunchAllowed"` 68 MonitorData struct { 69 Hudson_NodeMonitors_ArchitectureMonitor interface{} `json:"hudson.node_monitors.ArchitectureMonitor"` 70 Hudson_NodeMonitors_ClockMonitor interface{} `json:"hudson.node_monitors.ClockMonitor"` 71 Hudson_NodeMonitors_DiskSpaceMonitor interface{} `json:"hudson.node_monitors.DiskSpaceMonitor"` 72 Hudson_NodeMonitors_ResponseTimeMonitor struct { 73 Average int64 `json:"average"` 74 } `json:"hudson.node_monitors.ResponseTimeMonitor"` 75 Hudson_NodeMonitors_SwapSpaceMonitor interface{} `json:"hudson.node_monitors.SwapSpaceMonitor"` 76 Hudson_NodeMonitors_TemporarySpaceMonitor interface{} `json:"hudson.node_monitors.TemporarySpaceMonitor"` 77 } `json:"monitorData"` 78 NumExecutors int64 `json:"numExecutors"` 79 Offline bool `json:"offline"` 80 OfflineCause struct{} `json:"offlineCause"` 81 OfflineCauseReason string `json:"offlineCauseReason"` 82 OneOffExecutors []interface{} `json:"oneOffExecutors"` 83 TemporarilyOffline bool `json:"temporarilyOffline"` 84 } 85 86 func (n *Node) Info(ctx context.Context) (*NodeResponse, error) { 87 _, err := n.Poll(ctx) 88 if err != nil { 89 return nil, err 90 } 91 return n.Raw, nil 92 } 93 94 func (n *Node) GetName() string { 95 return n.Raw.DisplayName 96 } 97 98 func (n *Node) Delete(ctx context.Context) (bool, error) { 99 resp, err := n.Jenkins.Requester.Post(ctx, n.Base+"/doDelete", nil, nil, nil) 100 if err != nil { 101 return false, err 102 } 103 return resp.StatusCode == 200, nil 104 } 105 106 func (n *Node) IsOnline(ctx context.Context) (bool, error) { 107 _, err := n.Poll(ctx) 108 if err != nil { 109 return false, err 110 } 111 return !n.Raw.Offline, nil 112 } 113 114 func (n *Node) IsTemporarilyOffline(ctx context.Context) (bool, error) { 115 _, err := n.Poll(ctx) 116 if err != nil { 117 return false, err 118 } 119 return n.Raw.TemporarilyOffline, nil 120 } 121 122 func (n *Node) IsIdle(ctx context.Context) (bool, error) { 123 _, err := n.Poll(ctx) 124 if err != nil { 125 return false, err 126 } 127 return n.Raw.Idle, nil 128 } 129 130 func (n *Node) IsJnlpAgent(ctx context.Context) (bool, error) { 131 _, err := n.Poll(ctx) 132 if err != nil { 133 return false, err 134 } 135 return n.Raw.JnlpAgent, nil 136 } 137 138 func (n *Node) SetOnline(ctx context.Context) (bool, error) { 139 _, err := n.Poll(ctx) 140 141 if err != nil { 142 return false, err 143 } 144 145 if n.Raw.Offline && !n.Raw.TemporarilyOffline { 146 return false, errors.New("Node is Permanently offline, can't bring it up") 147 } 148 149 if n.Raw.Offline && n.Raw.TemporarilyOffline { 150 return n.ToggleTemporarilyOffline(ctx) 151 } 152 153 return true, nil 154 } 155 156 func (n *Node) SetOffline(ctx context.Context, options ...interface{}) (bool, error) { 157 if !n.Raw.Offline { 158 return n.ToggleTemporarilyOffline(ctx, options...) 159 } 160 return false, errors.New("Node already Offline") 161 } 162 163 func (n *Node) ToggleTemporarilyOffline(ctx context.Context, options ...interface{}) (bool, error) { 164 state_before, err := n.IsTemporarilyOffline(ctx) 165 if err != nil { 166 return false, err 167 } 168 qr := map[string]string{"offlineMessage": "requested from gojenkins"} 169 if len(options) > 0 { 170 qr["offlineMessage"] = options[0].(string) 171 } 172 _, err = n.Jenkins.Requester.Post(ctx, n.Base+"/toggleOffline", nil, nil, qr) 173 if err != nil { 174 return false, err 175 } 176 new_state, err := n.IsTemporarilyOffline(ctx) 177 if err != nil { 178 return false, err 179 } 180 if state_before == new_state { 181 return false, errors.New("Node state not changed") 182 } 183 return true, nil 184 } 185 186 func (n *Node) Poll(ctx context.Context) (int, error) { 187 response, err := n.Jenkins.Requester.GetJSON(ctx, n.Base, n.Raw, nil) 188 if err != nil { 189 return 0, err 190 } 191 return response.StatusCode, nil 192 } 193 194 func (n *Node) LaunchNodeBySSH(ctx context.Context) (int, error) { 195 qr := map[string]string{ 196 "json": "", 197 "Submit": "Launch slave agent", 198 } 199 response, err := n.Jenkins.Requester.Post(ctx, n.Base+"/launchSlaveAgent", nil, nil, qr) 200 if err != nil { 201 return 0, err 202 } 203 return response.StatusCode, nil 204 } 205 206 func (n *Node) Disconnect(ctx context.Context) (int, error) { 207 qr := map[string]string{ 208 "offlineMessage": "", 209 "json": makeJson(map[string]string{"offlineMessage": ""}), 210 "Submit": "Yes", 211 } 212 response, err := n.Jenkins.Requester.Post(ctx, n.Base+"/doDisconnect", nil, nil, qr) 213 if err != nil { 214 return 0, err 215 } 216 return response.StatusCode, nil 217 } 218 219 func (n *Node) GetLogText(ctx context.Context) (string, error) { 220 var log string 221 222 _, err := n.Jenkins.Requester.Post(ctx, n.Base+"/log", nil, nil, nil) 223 if err != nil { 224 return "", err 225 } 226 227 qr := map[string]string{"start": "0"} 228 _, err = n.Jenkins.Requester.GetJSON(ctx, n.Base+"/logText/progressiveHtml/", &log, qr) 229 if err != nil { 230 return "", nil 231 } 232 233 return log, nil 234 }