1
1
package coderd
2
2
3
3
import (
4
+ "context"
4
5
"crypto/tls"
5
6
"crypto/x509"
6
7
"fmt"
@@ -18,10 +19,13 @@ import (
18
19
"github.com/go-chi/chi/v5/middleware"
19
20
"github.com/google/uuid"
20
21
"github.com/klauspost/compress/zstd"
22
+ "github.com/moby/moby/pkg/namesgenerator"
21
23
"github.com/prometheus/client_golang/prometheus"
22
24
"go.opentelemetry.io/otel/trace"
23
25
"golang.org/x/xerrors"
24
26
"google.golang.org/api/idtoken"
27
+ "storj.io/drpc/drpcmux"
28
+ "storj.io/drpc/drpcserver"
25
29
"tailscale.com/derp"
26
30
"tailscale.com/derp/derphttp"
27
31
"tailscale.com/tailcfg"
@@ -37,12 +41,15 @@ import (
37
41
"github.com/coder/coder/coderd/httpapi"
38
42
"github.com/coder/coder/coderd/httpmw"
39
43
"github.com/coder/coder/coderd/metricscache"
44
+ "github.com/coder/coder/coderd/provisionerdserver"
40
45
"github.com/coder/coder/coderd/rbac"
41
46
"github.com/coder/coder/coderd/telemetry"
42
47
"github.com/coder/coder/coderd/tracing"
43
48
"github.com/coder/coder/coderd/workspacequota"
44
49
"github.com/coder/coder/coderd/wsconncache"
45
50
"github.com/coder/coder/codersdk"
51
+ "github.com/coder/coder/provisionerd/proto"
52
+ "github.com/coder/coder/provisionersdk"
46
53
"github.com/coder/coder/site"
47
54
"github.com/coder/coder/tailnet"
48
55
)
@@ -329,13 +336,6 @@ func New(options *Options) *API {
329
336
r .Get ("/{fileID}" , api .fileByID )
330
337
r .Post ("/" , api .postFile )
331
338
})
332
-
333
- r .Route ("/provisionerdaemons" , func (r chi.Router ) {
334
- r .Use (
335
- apiKeyMiddleware ,
336
- )
337
- r .Get ("/" , api .provisionerDaemons )
338
- })
339
339
r .Route ("/organizations" , func (r chi.Router ) {
340
340
r .Use (
341
341
apiKeyMiddleware ,
@@ -641,3 +641,59 @@ func compressHandler(h http.Handler) http.Handler {
641
641
642
642
return cmp .Handler (h )
643
643
}
644
+
645
+ // CreateInMemoryProvisionerDaemon is an in-memory connection to a provisionerd. Useful when starting coderd and provisionerd
646
+ // in the same process.
647
+ func (api * API ) CreateInMemoryProvisionerDaemon (ctx context.Context ) (client proto.DRPCProvisionerDaemonClient , err error ) {
648
+ clientSession , serverSession := provisionersdk .TransportPipe ()
649
+ defer func () {
650
+ if err != nil {
651
+ _ = clientSession .Close ()
652
+ _ = serverSession .Close ()
653
+ }
654
+ }()
655
+
656
+ name := namesgenerator .GetRandomName (1 )
657
+ daemon , err := api .Database .InsertProvisionerDaemon (ctx , database.InsertProvisionerDaemonParams {
658
+ ID : uuid .New (),
659
+ CreatedAt : database .Now (),
660
+ Name : name ,
661
+ Provisioners : []database.ProvisionerType {database .ProvisionerTypeEcho , database .ProvisionerTypeTerraform },
662
+ })
663
+ if err != nil {
664
+ return nil , xerrors .Errorf ("insert provisioner daemon %q: %w" , name , err )
665
+ }
666
+
667
+ mux := drpcmux .New ()
668
+ err = proto .DRPCRegisterProvisionerDaemon (mux , & provisionerdserver.Server {
669
+ AccessURL : api .AccessURL ,
670
+ ID : daemon .ID ,
671
+ Database : api .Database ,
672
+ Pubsub : api .Pubsub ,
673
+ Provisioners : daemon .Provisioners ,
674
+ Telemetry : api .Telemetry ,
675
+ Logger : api .Logger .Named (fmt .Sprintf ("provisionerd-%s" , daemon .Name )),
676
+ })
677
+ if err != nil {
678
+ return nil , err
679
+ }
680
+ server := drpcserver .NewWithOptions (mux , drpcserver.Options {
681
+ Log : func (err error ) {
682
+ if xerrors .Is (err , io .EOF ) {
683
+ return
684
+ }
685
+ api .Logger .Debug (ctx , "drpc server error" , slog .Error (err ))
686
+ },
687
+ })
688
+ go func () {
689
+ err := server .Serve (ctx , serverSession )
690
+ if err != nil && ! xerrors .Is (err , io .EOF ) {
691
+ api .Logger .Debug (ctx , "provisioner daemon disconnected" , slog .Error (err ))
692
+ }
693
+ // close the sessions so we don't leak goroutines serving them.
694
+ _ = clientSession .Close ()
695
+ _ = serverSession .Close ()
696
+ }()
697
+
698
+ return proto .NewDRPCProvisionerDaemonClient (provisionersdk .Conn (clientSession )), nil
699
+ }
0 commit comments