code.gitea.io/gitea@v1.19.3/modules/private/manager.go (about) 1 // Copyright 2020 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package private 5 6 import ( 7 "context" 8 "fmt" 9 "io" 10 "net/http" 11 "net/url" 12 "strconv" 13 "time" 14 15 "code.gitea.io/gitea/modules/json" 16 "code.gitea.io/gitea/modules/setting" 17 ) 18 19 // Shutdown calls the internal shutdown function 20 func Shutdown(ctx context.Context) (int, string) { 21 reqURL := setting.LocalURL + "api/internal/manager/shutdown" 22 23 req := newInternalRequest(ctx, reqURL, "POST") 24 resp, err := req.Response() 25 if err != nil { 26 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 27 } 28 defer resp.Body.Close() 29 30 if resp.StatusCode != http.StatusOK { 31 return resp.StatusCode, decodeJSONError(resp).Err 32 } 33 34 return http.StatusOK, "Shutting down" 35 } 36 37 // Restart calls the internal restart function 38 func Restart(ctx context.Context) (int, string) { 39 reqURL := setting.LocalURL + "api/internal/manager/restart" 40 41 req := newInternalRequest(ctx, reqURL, "POST") 42 resp, err := req.Response() 43 if err != nil { 44 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 45 } 46 defer resp.Body.Close() 47 48 if resp.StatusCode != http.StatusOK { 49 return resp.StatusCode, decodeJSONError(resp).Err 50 } 51 52 return http.StatusOK, "Restarting" 53 } 54 55 // FlushOptions represents the options for the flush call 56 type FlushOptions struct { 57 Timeout time.Duration 58 NonBlocking bool 59 } 60 61 // FlushQueues calls the internal flush-queues function 62 func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) (int, string) { 63 reqURL := setting.LocalURL + "api/internal/manager/flush-queues" 64 65 req := newInternalRequest(ctx, reqURL, "POST") 66 if timeout > 0 { 67 req.SetTimeout(timeout+10*time.Second, timeout+10*time.Second) 68 } 69 req = req.Header("Content-Type", "application/json") 70 jsonBytes, _ := json.Marshal(FlushOptions{ 71 Timeout: timeout, 72 NonBlocking: nonBlocking, 73 }) 74 req.Body(jsonBytes) 75 resp, err := req.Response() 76 if err != nil { 77 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 78 } 79 defer resp.Body.Close() 80 81 if resp.StatusCode != http.StatusOK { 82 return resp.StatusCode, decodeJSONError(resp).Err 83 } 84 85 return http.StatusOK, "Flushed" 86 } 87 88 // PauseLogging pauses logging 89 func PauseLogging(ctx context.Context) (int, string) { 90 reqURL := setting.LocalURL + "api/internal/manager/pause-logging" 91 92 req := newInternalRequest(ctx, reqURL, "POST") 93 resp, err := req.Response() 94 if err != nil { 95 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 96 } 97 defer resp.Body.Close() 98 99 if resp.StatusCode != http.StatusOK { 100 return resp.StatusCode, decodeJSONError(resp).Err 101 } 102 103 return http.StatusOK, "Logging Paused" 104 } 105 106 // ResumeLogging resumes logging 107 func ResumeLogging(ctx context.Context) (int, string) { 108 reqURL := setting.LocalURL + "api/internal/manager/resume-logging" 109 110 req := newInternalRequest(ctx, reqURL, "POST") 111 resp, err := req.Response() 112 if err != nil { 113 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 114 } 115 defer resp.Body.Close() 116 117 if resp.StatusCode != http.StatusOK { 118 return resp.StatusCode, decodeJSONError(resp).Err 119 } 120 121 return http.StatusOK, "Logging Restarted" 122 } 123 124 // ReleaseReopenLogging releases and reopens logging files 125 func ReleaseReopenLogging(ctx context.Context) (int, string) { 126 reqURL := setting.LocalURL + "api/internal/manager/release-and-reopen-logging" 127 128 req := newInternalRequest(ctx, reqURL, "POST") 129 resp, err := req.Response() 130 if err != nil { 131 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 132 } 133 defer resp.Body.Close() 134 135 if resp.StatusCode != http.StatusOK { 136 return resp.StatusCode, decodeJSONError(resp).Err 137 } 138 139 return http.StatusOK, "Logging Restarted" 140 } 141 142 // SetLogSQL sets database logging 143 func SetLogSQL(ctx context.Context, on bool) (int, string) { 144 reqURL := setting.LocalURL + "api/internal/manager/set-log-sql?on=" + strconv.FormatBool(on) 145 146 req := newInternalRequest(ctx, reqURL, "POST") 147 resp, err := req.Response() 148 if err != nil { 149 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 150 } 151 defer resp.Body.Close() 152 153 if resp.StatusCode != http.StatusOK { 154 return resp.StatusCode, decodeJSONError(resp).Err 155 } 156 157 return http.StatusOK, "Log SQL setting set" 158 } 159 160 // LoggerOptions represents the options for the add logger call 161 type LoggerOptions struct { 162 Group string 163 Name string 164 Mode string 165 Config map[string]interface{} 166 } 167 168 // AddLogger adds a logger 169 func AddLogger(ctx context.Context, group, name, mode string, config map[string]interface{}) (int, string) { 170 reqURL := setting.LocalURL + "api/internal/manager/add-logger" 171 172 req := newInternalRequest(ctx, reqURL, "POST") 173 req = req.Header("Content-Type", "application/json") 174 jsonBytes, _ := json.Marshal(LoggerOptions{ 175 Group: group, 176 Name: name, 177 Mode: mode, 178 Config: config, 179 }) 180 req.Body(jsonBytes) 181 resp, err := req.Response() 182 if err != nil { 183 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 184 } 185 defer resp.Body.Close() 186 187 if resp.StatusCode != http.StatusOK { 188 return resp.StatusCode, decodeJSONError(resp).Err 189 } 190 191 return http.StatusOK, "Added" 192 } 193 194 // RemoveLogger removes a logger 195 func RemoveLogger(ctx context.Context, group, name string) (int, string) { 196 reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/remove-logger/%s/%s", url.PathEscape(group), url.PathEscape(name)) 197 198 req := newInternalRequest(ctx, reqURL, "POST") 199 resp, err := req.Response() 200 if err != nil { 201 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 202 } 203 defer resp.Body.Close() 204 205 if resp.StatusCode != http.StatusOK { 206 return resp.StatusCode, decodeJSONError(resp).Err 207 } 208 209 return http.StatusOK, "Removed" 210 } 211 212 // Processes return the current processes from this gitea instance 213 func Processes(ctx context.Context, out io.Writer, flat, noSystem, stacktraces, json bool, cancel string) (int, string) { 214 reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/processes?flat=%t&no-system=%t&stacktraces=%t&json=%t&cancel-pid=%s", flat, noSystem, stacktraces, json, url.QueryEscape(cancel)) 215 216 req := newInternalRequest(ctx, reqURL, "GET") 217 resp, err := req.Response() 218 if err != nil { 219 return http.StatusInternalServerError, fmt.Sprintf("Unable to contact gitea: %v", err.Error()) 220 } 221 defer resp.Body.Close() 222 223 if resp.StatusCode != http.StatusOK { 224 return resp.StatusCode, decodeJSONError(resp).Err 225 } 226 227 _, err = io.Copy(out, resp.Body) 228 if err != nil { 229 return http.StatusInternalServerError, err.Error() 230 } 231 return http.StatusOK, "" 232 }