@@ -3,14 +3,22 @@ package database
3
3
import (
4
4
"context"
5
5
"fmt"
6
+ "github.com/jackc/pgx/v4"
7
+ "sync"
6
8
"time"
7
9
8
10
"github.com/jackc/pgx/v4/pgxpool"
9
11
)
10
12
13
+ const (
14
+ ControlPlaneCidr = "10.255.240.0/21"
15
+ DataPlaneCidr = "10.255.248.0/21"
16
+ )
17
+
11
18
type APIServerDB interface {
12
19
ReadClients () ([]Client , error )
13
20
UpdateClientStatus ([]Client ) error
21
+ AddClient (username , publicKey , serial string ) error
14
22
}
15
23
16
24
type Client struct {
@@ -101,3 +109,68 @@ func (d *database) UpdateClientStatus(clients []Client) error {
101
109
102
110
return tx .Commit (ctx )
103
111
}
112
+
113
+ var mux sync.Mutex
114
+
115
+ func (d * database ) AddClient (username , publicKey , serial string ) error {
116
+ mux .Lock ()
117
+ defer mux .Unlock ()
118
+
119
+ ctx := context .Background ()
120
+
121
+ tx , err := d .conn .Begin (ctx )
122
+ if err != nil {
123
+ return fmt .Errorf ("start transaction: %w" , err )
124
+ }
125
+
126
+ defer tx .Rollback (ctx )
127
+
128
+ ips , err := ips (tx , ctx )
129
+ if err != nil {
130
+ return fmt .Errorf ("fetch ips: %w" , err )
131
+ }
132
+
133
+ ip , err := FindAvailableIP (ControlPlaneCidr , ips )
134
+ if err != nil {
135
+ return fmt .Errorf ("finding available ip: %w" , err )
136
+ }
137
+
138
+ statement := `
139
+ WITH
140
+ client_key AS
141
+ (INSERT INTO client (serial, healthy) VALUES ($1, false) RETURNING id),
142
+ peer_control_key AS
143
+ (INSERT INTO peer (public_key, ip, type) VALUES ($2, $3, 'control') RETURNING id)
144
+ INSERT
145
+ INTO client_peer(client_id, peer_id)
146
+ (
147
+ SELECT client_key.id, peer_control_key.id
148
+ FROM client_key, peer_control_key
149
+ );
150
+ `
151
+ _ , err = tx .Exec (ctx , statement , serial , publicKey , ip )
152
+
153
+ if err != nil {
154
+ return fmt .Errorf ("inserting new client: %w" , err )
155
+ }
156
+
157
+ return nil
158
+ }
159
+
160
+ func ips (tx pgx.Tx , ctx context.Context ) (ips []string , err error ) {
161
+ rows , err := tx .Query (ctx , "SELECT ip FROM peer;" )
162
+ if err != nil {
163
+ return nil , fmt .Errorf ("get peers: %w" , err )
164
+ }
165
+
166
+ if rows .Err () != nil {
167
+ return nil , fmt .Errorf ("get peers: %w" , err )
168
+ }
169
+
170
+ err = rows .Scan (ips )
171
+ if err != nil {
172
+ return nil , fmt .Errorf ("scan peers: %w" , err )
173
+ }
174
+
175
+ return
176
+ }
0 commit comments