44 "bytes"
55 "encoding/json"
66 "fmt"
7+ "io"
78 "net/http"
89 "strings"
910 "time"
@@ -17,25 +18,6 @@ var httpClient = &http.Client{
1718 Timeout : 5 * time .Second ,
1819}
1920
20- func RenderAuthConfig (options configmanager.RawOptions ) (configmanager.RawOptions , error ) {
21- opts , err := NewOptions (options )
22- if err != nil {
23- return nil , err
24- }
25-
26- for _ , p := range opts .Plugins {
27- for _ , c := range p .Connections {
28- c .Token = c .Authx .Token
29- c .Username = c .Authx .Username
30- c .Password = c .Authx .Password
31- c .AppId = c .Authx .AppId
32- c .SecretKey = c .Authx .SecretKey
33- }
34- }
35-
36- return opts .Encode ()
37- }
38-
3921func ApplyConfig (options configmanager.RawOptions ) error {
4022 opts , err := NewOptions (options )
4123 if err != nil {
@@ -55,42 +37,92 @@ func ApplyConfig(options configmanager.RawOptions) error {
5537func createConnections (host string , pluginName string , connections []Connection ) error {
5638 for i , c := range connections {
5739 log .Infof ("Connection %d: %s" , i , c .Name )
58- configs , err := json .Marshal (c )
59- if err != nil {
60- return err
61- }
62- log .Debugf ("Connection configs: %s" , string (configs ))
63-
64- url := fmt .Sprintf ("%s/plugins/%s/connections" , strings .TrimRight (host , "/" ), pluginName )
65- log .Debugf ("URL: %s" , url )
66-
67- if err := createConnection (url , configs ); err != nil {
40+ if err := createConnection (host , pluginName , c ); err != nil {
6841 return err
6942 }
7043 }
71-
7244 log .Infof ("All %s connections have been created." , pluginName )
7345 return nil
7446}
7547
76- func createConnection (url string , bodyWithJson [] byte ) error {
77- req , err := http . NewRequest ( http . MethodPost , url , bytes . NewBuffer ( bodyWithJson ) )
48+ func createConnection (host string , pluginName string , c Connection ) error {
49+ configs , err := json . Marshal ( c )
7850 if err != nil {
7951 return err
8052 }
81- req .Header .Set ("Content-Type" , "application/json" )
53+ log .Debugf ("Connection configs: %s" , string (configs ))
54+ url := fmt .Sprintf ("%s/plugins/%s/connections" , strings .TrimRight (host , "/" ), pluginName )
55+ log .Debugf ("URL: %s" , url )
56+ if _ , err = apiRequest (http .MethodPost , url , configs ); err != nil {
57+ return err
58+ }
59+ return nil
60+ }
8261
83- resp , err := httpClient .Do (req )
62+ // update existed connection in devlake backend
63+ func updateConnection (host string , pluginName string , c Connection ) error {
64+ configs , err := json .Marshal (c )
8465 if err != nil {
8566 return err
8667 }
68+ log .Debugf ("UPDATE Connection configs: %s" , string (configs ))
69+ url := fmt .Sprintf ("%s/plugins/%s/connections/%d" , strings .TrimRight (host , "/" ), pluginName , c .ID )
70+ log .Debugf ("URL: %s" , url )
71+ if _ , err = apiRequest (http .MethodPatch , url , configs ); err != nil {
72+ return err
73+ }
74+ return nil
75+ }
76+
77+ // delete existed connection in devlake backend
78+ func deleteConnection (host string , pluginName string , c Connection ) error {
79+ configs , err := json .Marshal (c )
80+ if err != nil {
81+ return err
82+ }
83+ log .Debugf ("DELETE Connection configs: %s" , string (configs ))
84+ url := fmt .Sprintf ("%s/plugins/%s/connections/%d" , strings .TrimRight (host , "/" ), pluginName , c .ID )
85+ log .Debugf ("URL: %s" , url )
86+ if _ , err = apiRequest (http .MethodDelete , url , configs ); err != nil {
87+ return err
88+ }
89+ return nil
90+ }
91+
92+ func getConnections (host string , pluginName string ) ([]Connection , error ) {
93+ url := fmt .Sprintf ("%s/plugins/%s/connections" , strings .TrimRight (host , "/" ), pluginName )
94+ log .Debugf ("URL: %s" , url )
95+ resp , err := apiRequest (http .MethodGet , url , nil )
96+ if err != nil {
97+ return nil , err
98+ }
8799 defer resp .Body .Close ()
100+ resBody , err := io .ReadAll (resp .Body )
101+ if err != nil {
102+ return nil , err
103+ }
104+ connections := make ([]Connection , 0 )
105+ err = json .Unmarshal (resBody , & connections )
106+ if err != nil {
107+ return nil , err
108+ }
109+ return connections , nil
110+ }
88111
112+ func apiRequest (method string , url string , bodyWithJson []byte ) (* http.Response , error ) {
113+ req , err := http .NewRequest (method , url , bytes .NewBuffer (bodyWithJson ))
114+ if err != nil {
115+ return nil , err
116+ }
117+ req .Header .Set ("Content-Type" , "application/json" )
118+ resp , err := httpClient .Do (req )
119+ if err != nil {
120+ return nil , err
121+ }
89122 if resp .StatusCode == http .StatusOK {
90- return nil
123+ return resp , nil
91124 }
92-
93- return fmt .Errorf (resp .Status )
125+ return nil , fmt .Errorf (resp .Status )
94126}
95127
96128func DeleteConfig (options configmanager.RawOptions ) error {
@@ -99,11 +131,71 @@ func DeleteConfig(options configmanager.RawOptions) error {
99131}
100132
101133func UpdateConfig (options configmanager.RawOptions ) error {
102- // TODO(daniel-hutao): implement later
134+ opts , err := NewOptions (options )
135+ if err != nil {
136+ return err
137+ }
138+ for _ , p := range opts .Plugins {
139+ if updatePluginConfig (opts .DevLakeAddr , p ) != nil {
140+ return err
141+ }
142+ }
143+ return nil
144+ }
145+
146+ func updatePluginConfig (devlakeAddr string , plugin DevLakePlugin ) error {
147+ connections , err := getConnections (devlakeAddr , plugin .Name )
148+ if err != nil {
149+ return err
150+ }
151+
152+ // Connection.Name -> Connection for config
153+ connMapForConfig := make (map [string ]Connection )
154+ // Connection.Name -> Connection for status
155+ connMapForStatus := make (map [string ]Connection )
156+ for _ , c := range plugin .Connections {
157+ connMapForConfig [c .Name ] = c
158+ }
159+ for _ , c := range connections {
160+ connMapForStatus [c .Name ] = c
161+ }
162+
163+ return updatePluginConnections (connMapForConfig , connMapForStatus , devlakeAddr , plugin )
164+ }
165+
166+ func updatePluginConnections (connMapForConfig , connMapForStatus map [string ]Connection , devlakeAddr string , plugin DevLakePlugin ) error {
167+ for name := range connMapForConfig {
168+ // Create connection which is not in ResourceStatus
169+ c , ok := connMapForStatus [name ]
170+ if ok {
171+ if err := createConnection (devlakeAddr , plugin .Name , connMapForConfig [name ]); err != nil {
172+ return err
173+ }
174+ continue
175+ }
176+
177+ // Update connection which is different from State
178+ if c != connMapForConfig [name ] {
179+ if err := updateConnection (devlakeAddr , plugin .Name , connMapForStatus [name ]); err != nil {
180+ return err
181+ }
182+ }
183+ }
184+
185+ // Delete connection which is not in Config
186+ for name := range connMapForStatus {
187+ if _ , ok := connMapForConfig [name ]; ! ok {
188+ if err := deleteConnection (devlakeAddr , plugin .Name , connMapForStatus [name ]); err != nil {
189+ return err
190+ }
191+ }
192+ }
193+
103194 return nil
104195}
105196
106197func GetStatus (options configmanager.RawOptions ) (statemanager.ResourceStatus , error ) {
198+ // TODO(daniel-hutao): get the real status later
107199 resStatus := statemanager .ResourceStatus (options )
108200 return resStatus , nil
109201}
0 commit comments