docs: update docs about insecure skip verify

This commit is contained in:
Jacky 2024-07-30 15:17:43 +08:00
parent f1c0f8ddca
commit 6c7b644f60
No known key found for this signature in database
GPG key ID: 215C21B10DF38B4D
9 changed files with 467 additions and 443 deletions

View file

@ -1,18 +1,18 @@
package openai
import (
"context"
"crypto/tls"
"fmt"
"github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/internal/chatbot"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/sashabaranov/go-openai"
"io"
"net/http"
"net/url"
"context"
"crypto/tls"
"fmt"
"github.com/0xJacky/Nginx-UI/api"
"github.com/0xJacky/Nginx-UI/internal/chatbot"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
"github.com/sashabaranov/go-openai"
"io"
"net/http"
"net/url"
)
const ChatGPTInitPrompt = `You are a assistant who can help users write and optimise the configurations of Nginx,
@ -22,111 +22,111 @@ Later the language environment depends on the user message.
The first reply should involve the key information of the file and ask user what can you help them.`
func MakeChatCompletionRequest(c *gin.Context) {
var json struct {
Filepath string `json:"filepath"`
Messages []openai.ChatCompletionMessage `json:"messages"`
}
var json struct {
Filepath string `json:"filepath"`
Messages []openai.ChatCompletionMessage `json:"messages"`
}
if !api.BindAndValid(c, &json) {
return
}
if !api.BindAndValid(c, &json) {
return
}
messages := []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: ChatGPTInitPrompt,
},
}
messages := []openai.ChatCompletionMessage{
{
Role: openai.ChatMessageRoleSystem,
Content: ChatGPTInitPrompt,
},
}
messages = append(messages, json.Messages...)
messages = append(messages, json.Messages...)
if json.Filepath != "" {
messages = chatbot.ChatCompletionWithContext(json.Filepath, messages)
}
if json.Filepath != "" {
messages = chatbot.ChatCompletionWithContext(json.Filepath, messages)
}
// SSE server
c.Writer.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
c.Writer.Header().Set("Cache-Control", "no-cache")
c.Writer.Header().Set("Connection", "keep-alive")
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
// SSE server
c.Writer.Header().Set("Content-Type", "text/event-stream; charset=utf-8")
c.Writer.Header().Set("Cache-Control", "no-cache")
c.Writer.Header().Set("Connection", "keep-alive")
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
config := openai.DefaultConfig(settings.OpenAISettings.Token)
config := openai.DefaultConfig(settings.OpenAISettings.Token)
if settings.OpenAISettings.Proxy != "" {
proxyUrl, err := url.Parse(settings.OpenAISettings.Proxy)
if err != nil {
c.Stream(func(w io.Writer) bool {
c.SSEvent("message", gin.H{
"type": "error",
"content": err.Error(),
})
return false
})
return
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
}
config.HTTPClient = &http.Client{
Transport: transport,
}
}
if settings.OpenAISettings.Proxy != "" {
proxyUrl, err := url.Parse(settings.OpenAISettings.Proxy)
if err != nil {
c.Stream(func(w io.Writer) bool {
c.SSEvent("message", gin.H{
"type": "error",
"content": err.Error(),
})
return false
})
return
}
transport := &http.Transport{
Proxy: http.ProxyURL(proxyUrl),
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
}
config.HTTPClient = &http.Client{
Transport: transport,
}
}
if settings.OpenAISettings.BaseUrl != "" {
config.BaseURL = settings.OpenAISettings.BaseUrl
}
if settings.OpenAISettings.BaseUrl != "" {
config.BaseURL = settings.OpenAISettings.BaseUrl
}
openaiClient := openai.NewClientWithConfig(config)
ctx := context.Background()
openaiClient := openai.NewClientWithConfig(config)
ctx := context.Background()
req := openai.ChatCompletionRequest{
Model: settings.OpenAISettings.Model,
Messages: messages,
Stream: true,
}
stream, err := openaiClient.CreateChatCompletionStream(ctx, req)
if err != nil {
fmt.Printf("CompletionStream error: %v\n", err)
c.Stream(func(w io.Writer) bool {
c.SSEvent("message", gin.H{
"type": "error",
"content": err.Error(),
})
return false
})
return
}
defer stream.Close()
msgChan := make(chan string)
go func() {
defer close(msgChan)
for {
response, err := stream.Recv()
if errors.Is(err, io.EOF) {
fmt.Println()
return
}
req := openai.ChatCompletionRequest{
Model: settings.OpenAISettings.Model,
Messages: messages,
Stream: true,
}
stream, err := openaiClient.CreateChatCompletionStream(ctx, req)
if err != nil {
fmt.Printf("CompletionStream error: %v\n", err)
c.Stream(func(w io.Writer) bool {
c.SSEvent("message", gin.H{
"type": "error",
"content": err.Error(),
})
return false
})
return
}
defer stream.Close()
msgChan := make(chan string)
go func() {
defer close(msgChan)
for {
response, err := stream.Recv()
if errors.Is(err, io.EOF) {
fmt.Println()
return
}
if err != nil {
fmt.Printf("Stream error: %v\n", err)
return
}
if err != nil {
fmt.Printf("Stream error: %v\n", err)
return
}
message := fmt.Sprintf("%s", response.Choices[0].Delta.Content)
message := fmt.Sprintf("%s", response.Choices[0].Delta.Content)
msgChan <- message
}
}()
msgChan <- message
}
}()
c.Stream(func(w io.Writer) bool {
if m, ok := <-msgChan; ok {
c.SSEvent("message", gin.H{
"type": "message",
"content": m,
})
return true
}
return false
})
c.Stream(func(w io.Writer) bool {
if m, ok := <-msgChan; ok {
c.SSEvent("message", gin.H{
"type": "message",
"content": m,
})
return true
}
return false
})
}

View file

@ -145,3 +145,10 @@ Nginx UI will not create a system initial acme user, this means you can't apply
- Type: `string`
Use this option to customize the name of local server to be displayed in the environment indicator.
## InsecureSkipVerify
- Version`>= v2.0.0-beta.30`
- Type: `bool`
This option is used to skip the verification of the certificate of servers when Nginx UI sends requests to them.

View file

@ -3,24 +3,25 @@ Applicable for version v2.0.0-beta.23 and above.
## Server
| Configuration Setting | Environment Variable |
| ----------------------------- | ------------------------------------- |
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| Configuration Setting | Environment Variable |
|-----------------------|---------------------------------------|
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| InsecureSkipVerify | NGINX_UI_SERVER_INSECURE_SKIP_VERIFY |
## Nginx

View file

@ -132,3 +132,10 @@ Nginx UI 将不会创建系统初始的 acme 用户,这意味着您无法在
- 类型:`string`
使用此选项自定义本地服务器的名称,以在环境指示器中显示。
## InsecureSkipVerify
- 版本:`>= v2.0.0-beta.30`
- 类型: `bool`
此选项用于配置 Nginx UI 服务器在与其他服务器建立 TLS 连接时是否跳过证书验证。

View file

@ -3,24 +3,25 @@
## Server
| Configuration Setting | Environment Variable |
| ----------------------------- | ------------------------------------- |
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| Configuration Setting | Environment Variable |
|-------------------------| ------------------------------------- |
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| InsecureSkipVerify | NGINX_UI_SERVER_INSECURE_SKIP_VERIFY |
## Nginx

View file

@ -133,3 +133,10 @@ Nginx UI 將不會創建系統初始的 acme 使用者,這意味著您無法
- 類型:`string`
使用此選項自定義本地伺服器的名稱,以在環境指示器中顯示。
## InsecureSkipVerify
- 版本:`>= v2.0.0-beta.30`
- 類型: `bool`
此選項用於配置 Nginx UI 伺服器在與其他伺服器建立 TLS 連接時是否跳過證書驗證。

View file

@ -3,24 +3,25 @@
## Server
| Configuration Setting | Environment Variable |
| ----------------------------- | ------------------------------------- |
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| Configuration Setting | Environment Variable |
|------------------------| ------------------------------------- |
| HttpPort | NGINX_UI_SERVER_HTTP_PORT |
| RunMode | NGINX_UI_SERVER_RUN_MODE |
| JwtSecret | NGINX_UI_SERVER_JWT_SECRET |
| HTTPChallengePort | NGINX_UI_SERVER_HTTP_CHALLENGE_PORT |
| StartCmd | NGINX_UI_SERVER_START_CMD |
| Database | NGINX_UI_SERVER_DATABASE |
| CADir | NGINX_UI_SERVER_CA_DIR |
| GithubProxy | NGINX_UI_SERVER_GITHUB_PROXY |
| NodeSecret | NGINX_UI_SERVER_NODE_SECRET |
| Demo | NGINX_UI_SERVER_DEMO |
| PageSize | NGINX_UI_SERVER_PAGE_SIZE |
| HttpHost | NGINX_UI_SERVER_HTTP_HOST |
| CertRenewalInterval | NGINX_UI_SERVER_CERT_RENEWAL_INTERVAL |
| RecursiveNameservers | NGINX_UI_SERVER_RECURSIVE_NAMESERVERS |
| SkipInstallation | NGINX_UI_SERVER_SKIP_INSTALLATION |
| Name | NGINX_UI_SERVER_NAME |
| InsecureSkipVerify | NGINX_UI_SERVER_INSECURE_SKIP_VERIFY |
## Nginx

View file

@ -1,44 +1,44 @@
package analytic
import (
"crypto/tls"
"encoding/json"
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/internal/upgrader"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/shirou/gopsutil/v3/load"
"github.com/shirou/gopsutil/v3/net"
"io"
"net/http"
"net/url"
"sync"
"time"
"crypto/tls"
"encoding/json"
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/internal/upgrader"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/shirou/gopsutil/v3/load"
"github.com/shirou/gopsutil/v3/net"
"io"
"net/http"
"net/url"
"sync"
"time"
)
type NodeInfo struct {
NodeRuntimeInfo upgrader.RuntimeInfo `json:"node_runtime_info"`
Version string `json:"version"`
CPUNum int `json:"cpu_num"`
MemoryTotal string `json:"memory_total"`
DiskTotal string `json:"disk_total"`
NodeRuntimeInfo upgrader.RuntimeInfo `json:"node_runtime_info"`
Version string `json:"version"`
CPUNum int `json:"cpu_num"`
MemoryTotal string `json:"memory_total"`
DiskTotal string `json:"disk_total"`
}
type NodeStat struct {
AvgLoad *load.AvgStat `json:"avg_load"`
CPUPercent float64 `json:"cpu_percent"`
MemoryPercent float64 `json:"memory_percent"`
DiskPercent float64 `json:"disk_percent"`
Network net.IOCountersStat `json:"network"`
Status bool `json:"status"`
ResponseAt time.Time `json:"response_at"`
AvgLoad *load.AvgStat `json:"avg_load"`
CPUPercent float64 `json:"cpu_percent"`
MemoryPercent float64 `json:"memory_percent"`
DiskPercent float64 `json:"disk_percent"`
Network net.IOCountersStat `json:"network"`
Status bool `json:"status"`
ResponseAt time.Time `json:"response_at"`
}
type Node struct {
EnvironmentID int `json:"environment_id,omitempty"`
*model.Environment
NodeStat
NodeInfo
EnvironmentID int `json:"environment_id,omitempty"`
*model.Environment
NodeStat
NodeInfo
}
var mutex sync.Mutex
@ -48,74 +48,74 @@ type TNodeMap map[int]*Node
var NodeMap TNodeMap
func init() {
NodeMap = make(TNodeMap)
NodeMap = make(TNodeMap)
}
func GetNode(env *model.Environment) (n *Node) {
if env == nil {
// this should never happen
logger.Error("env is nil")
return
}
if !env.Enabled {
return &Node{
Environment: env,
}
}
n, ok := NodeMap[env.ID]
if !ok {
n = &Node{}
}
n.Environment = env
return n
if env == nil {
// this should never happen
logger.Error("env is nil")
return
}
if !env.Enabled {
return &Node{
Environment: env,
}
}
n, ok := NodeMap[env.ID]
if !ok {
n = &Node{}
}
n.Environment = env
return n
}
func InitNode(env *model.Environment) (n *Node) {
n = &Node{
Environment: env,
}
n = &Node{
Environment: env,
}
u, err := url.JoinPath(env.URL, "/api/node")
u, err := url.JoinPath(env.URL, "/api/node")
if err != nil {
logger.Error(err)
return
}
if err != nil {
logger.Error(err)
return
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
req, err := http.NewRequest("GET", u, nil)
if err != nil {
logger.Error(err)
return
}
req, err := http.NewRequest("GET", u, nil)
if err != nil {
logger.Error(err)
return
}
req.Header.Set("X-Node-Secret", env.Token)
req.Header.Set("X-Node-Secret", env.Token)
resp, err := client.Do(req)
resp, err := client.Do(req)
if err != nil {
logger.Error(err)
return
}
if err != nil {
logger.Error(err)
return
}
defer resp.Body.Close()
bytes, _ := io.ReadAll(resp.Body)
defer resp.Body.Close()
bytes, _ := io.ReadAll(resp.Body)
if resp.StatusCode != http.StatusOK {
logger.Error(string(bytes))
return
}
if resp.StatusCode != http.StatusOK {
logger.Error(string(bytes))
return
}
err = json.Unmarshal(bytes, &n.NodeInfo)
if err != nil {
logger.Error(err)
return
}
err = json.Unmarshal(bytes, &n.NodeInfo)
if err != nil {
logger.Error(err)
return
}
return
return
}

View file

@ -1,258 +1,258 @@
package config
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/0xJacky/Nginx-UI/internal/helper"
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/internal/nginx"
"github.com/0xJacky/Nginx-UI/internal/notification"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/query"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/0xJacky/Nginx-UI/internal/helper"
"github.com/0xJacky/Nginx-UI/internal/logger"
"github.com/0xJacky/Nginx-UI/internal/nginx"
"github.com/0xJacky/Nginx-UI/internal/notification"
"github.com/0xJacky/Nginx-UI/model"
"github.com/0xJacky/Nginx-UI/query"
"github.com/0xJacky/Nginx-UI/settings"
"github.com/gin-gonic/gin"
"io"
"net/http"
"os"
"path/filepath"
"strings"
)
type SyncConfigPayload struct {
Name string `json:"name"`
Filepath string `json:"filepath"`
NewFilepath string `json:"new_filepath"`
Content string `json:"content"`
Overwrite bool `json:"overwrite"`
Name string `json:"name"`
Filepath string `json:"filepath"`
NewFilepath string `json:"new_filepath"`
Content string `json:"content"`
Overwrite bool `json:"overwrite"`
}
func SyncToRemoteServer(c *model.Config, newFilepath string) (err error) {
if c.Filepath == "" || len(c.SyncNodeIds) == 0 {
return
}
if c.Filepath == "" || len(c.SyncNodeIds) == 0 {
return
}
nginxConfPath := nginx.GetConfPath()
if !helper.IsUnderDirectory(c.Filepath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
c.Filepath, nginxConfPath)
}
nginxConfPath := nginx.GetConfPath()
if !helper.IsUnderDirectory(c.Filepath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
c.Filepath, nginxConfPath)
}
if newFilepath != "" && !helper.IsUnderDirectory(newFilepath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
c.Filepath, nginxConfPath)
}
if newFilepath != "" && !helper.IsUnderDirectory(newFilepath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
c.Filepath, nginxConfPath)
}
currentPath := c.Filepath
if newFilepath != "" {
currentPath = newFilepath
}
configBytes, err := os.ReadFile(currentPath)
if err != nil {
return
}
currentPath := c.Filepath
if newFilepath != "" {
currentPath = newFilepath
}
configBytes, err := os.ReadFile(currentPath)
if err != nil {
return
}
payload := &SyncConfigPayload{
Name: c.Name,
Filepath: c.Filepath,
NewFilepath: newFilepath,
Content: string(configBytes),
Overwrite: c.SyncOverwrite,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return
}
payload := &SyncConfigPayload{
Name: c.Name,
Filepath: c.Filepath,
NewFilepath: newFilepath,
Content: string(configBytes),
Overwrite: c.SyncOverwrite,
}
payloadBytes, err := json.Marshal(payload)
if err != nil {
return
}
q := query.Environment
envs, _ := q.Where(q.ID.In(c.SyncNodeIds...)).Find()
for _, env := range envs {
go func() {
err := payload.deploy(env, c, payloadBytes)
if err != nil {
logger.Error(err)
}
}()
}
q := query.Environment
envs, _ := q.Where(q.ID.In(c.SyncNodeIds...)).Find()
for _, env := range envs {
go func() {
err := payload.deploy(env, c, payloadBytes)
if err != nil {
logger.Error(err)
}
}()
}
return
return
}
func SyncRenameOnRemoteServer(origPath, newPath string, syncNodeIds []int) (err error) {
if origPath == "" || newPath == "" || len(syncNodeIds) == 0 {
return
}
if origPath == "" || newPath == "" || len(syncNodeIds) == 0 {
return
}
nginxConfPath := nginx.GetConfPath()
if !helper.IsUnderDirectory(origPath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
origPath, nginxConfPath)
}
nginxConfPath := nginx.GetConfPath()
if !helper.IsUnderDirectory(origPath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
origPath, nginxConfPath)
}
if !helper.IsUnderDirectory(newPath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
newPath, nginxConfPath)
}
if !helper.IsUnderDirectory(newPath, nginxConfPath) {
return fmt.Errorf("config: %s is not under the nginx conf path: %s",
newPath, nginxConfPath)
}
payload := &RenameConfigPayload{
Filepath: origPath,
NewFilepath: newPath,
}
payload := &RenameConfigPayload{
Filepath: origPath,
NewFilepath: newPath,
}
q := query.Environment
envs, _ := q.Where(q.ID.In(syncNodeIds...)).Find()
for _, env := range envs {
go func() {
err := payload.rename(env)
if err != nil {
logger.Error(err)
}
}()
}
q := query.Environment
envs, _ := q.Where(q.ID.In(syncNodeIds...)).Find()
for _, env := range envs {
go func() {
err := payload.rename(env)
if err != nil {
logger.Error(err)
}
}()
}
return
return
}
type SyncNotificationPayload struct {
StatusCode int `json:"status_code"`
ConfigName string `json:"config_name"`
EnvName string `json:"env_name"`
RespBody string `json:"resp_body"`
StatusCode int `json:"status_code"`
ConfigName string `json:"config_name"`
EnvName string `json:"env_name"`
RespBody string `json:"resp_body"`
}
func (p *SyncConfigPayload) deploy(env *model.Environment, c *model.Config, payloadBytes []byte) (err error) {
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
url, err := env.GetUrl("/api/config")
if err != nil {
return
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return
}
req.Header.Set("X-Node-Secret", env.Token)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
url, err := env.GetUrl("/api/config")
if err != nil {
return
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return
}
req.Header.Set("X-Node-Secret", env.Token)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return
}
notificationPayload := &SyncNotificationPayload{
StatusCode: resp.StatusCode,
ConfigName: c.Name,
EnvName: env.Name,
RespBody: string(respBody),
}
notificationPayload := &SyncNotificationPayload{
StatusCode: resp.StatusCode,
ConfigName: c.Name,
EnvName: env.Name,
RespBody: string(respBody),
}
notificationPayloadBytes, err := json.Marshal(notificationPayload)
if err != nil {
return
}
notificationPayloadBytes, err := json.Marshal(notificationPayload)
if err != nil {
return
}
if resp.StatusCode != http.StatusOK {
notification.Error("Sync Config Error", string(notificationPayloadBytes))
return
}
if resp.StatusCode != http.StatusOK {
notification.Error("Sync Config Error", string(notificationPayloadBytes))
return
}
notification.Success("Sync Config Success", string(notificationPayloadBytes))
notification.Success("Sync Config Success", string(notificationPayloadBytes))
// handle rename
if p.NewFilepath == "" || p.Filepath == p.NewFilepath {
return
}
// handle rename
if p.NewFilepath == "" || p.Filepath == p.NewFilepath {
return
}
payload := &RenameConfigPayload{
Filepath: p.Filepath,
NewFilepath: p.NewFilepath,
}
payload := &RenameConfigPayload{
Filepath: p.Filepath,
NewFilepath: p.NewFilepath,
}
err = payload.rename(env)
err = payload.rename(env)
return
return
}
type RenameConfigPayload struct {
Filepath string `json:"filepath"`
NewFilepath string `json:"new_filepath"`
Filepath string `json:"filepath"`
NewFilepath string `json:"new_filepath"`
}
type SyncRenameNotificationPayload struct {
StatusCode int `json:"status_code"`
OrigPath string `json:"orig_path"`
NewPath string `json:"new_path"`
EnvName string `json:"env_name"`
RespBody string `json:"resp_body"`
StatusCode int `json:"status_code"`
OrigPath string `json:"orig_path"`
NewPath string `json:"new_path"`
EnvName string `json:"env_name"`
RespBody string `json:"resp_body"`
}
func (p *RenameConfigPayload) rename(env *model.Environment) (err error) {
// handle rename
if p.NewFilepath == "" || p.Filepath == p.NewFilepath {
return
}
// handle rename
if p.NewFilepath == "" || p.Filepath == p.NewFilepath {
return
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: settings.ServerSettings.InsecureSkipVerify},
},
}
payloadBytes, err := json.Marshal(gin.H{
"base_path": strings.ReplaceAll(filepath.Dir(p.Filepath), nginx.GetConfPath(), ""),
"orig_name": filepath.Base(p.Filepath),
"new_name": filepath.Base(p.NewFilepath),
})
if err != nil {
return
}
url, err := env.GetUrl("/api/config_rename")
if err != nil {
return
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return
}
req.Header.Set("X-Node-Secret", env.Token)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
payloadBytes, err := json.Marshal(gin.H{
"base_path": strings.ReplaceAll(filepath.Dir(p.Filepath), nginx.GetConfPath(), ""),
"orig_name": filepath.Base(p.Filepath),
"new_name": filepath.Base(p.NewFilepath),
})
if err != nil {
return
}
url, err := env.GetUrl("/api/config_rename")
if err != nil {
return
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(payloadBytes))
if err != nil {
return
}
req.Header.Set("X-Node-Secret", env.Token)
resp, err := client.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return
}
notificationPayload := &SyncRenameNotificationPayload{
StatusCode: resp.StatusCode,
OrigPath: p.Filepath,
NewPath: p.NewFilepath,
EnvName: env.Name,
RespBody: string(respBody),
}
notificationPayload := &SyncRenameNotificationPayload{
StatusCode: resp.StatusCode,
OrigPath: p.Filepath,
NewPath: p.NewFilepath,
EnvName: env.Name,
RespBody: string(respBody),
}
notificationPayloadBytes, err := json.Marshal(notificationPayload)
if err != nil {
return
}
notificationPayloadBytes, err := json.Marshal(notificationPayload)
if err != nil {
return
}
if resp.StatusCode != http.StatusOK {
notification.Error("Rename Remote Config Error", string(notificationPayloadBytes))
return
}
if resp.StatusCode != http.StatusOK {
notification.Error("Rename Remote Config Error", string(notificationPayloadBytes))
return
}
notification.Success("Rename Remote Config Success", string(notificationPayloadBytes))
notification.Success("Rename Remote Config Success", string(notificationPayloadBytes))
return
return
}