/
aspire_service.go
139 lines (111 loc) · 3.89 KB
/
aspire_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package vsrpc
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"github.com/azure/azure-dev/cli/azd/internal/appdetect"
"github.com/azure/azure-dev/cli/azd/pkg/apphost"
"github.com/azure/azure-dev/cli/azd/pkg/environment/azdcontext"
"github.com/azure/azure-dev/cli/azd/pkg/project"
"github.com/azure/azure-dev/cli/azd/pkg/tools/dotnet"
)
// aspireService is the RPC server for the '/AspireService/v1.0' endpoint.
type aspireService struct {
server *Server
}
func newAspireService(server *Server) *aspireService {
return &aspireService{
server: server,
}
}
// GetAspireHostAsync is the server implementation of:
// ValueTask<AspireHost> GetAspireHostAsync(Session session, string aspireEnv, CancellationToken cancellationToken).
func (s *aspireService) GetAspireHostAsync(
ctx context.Context, rc RequestContext, aspireEnv string, observer IObserver[ProgressMessage],
) (*AspireHost, error) {
session, err := s.server.validateSession(ctx, rc.Session)
if err != nil {
return nil, err
}
var c struct {
azdContext *azdcontext.AzdContext `container:"type"`
dotnetCli dotnet.DotNetCli `container:"type"`
}
container, err := session.newContainer()
if err != nil {
return nil, err
}
if err := container.Fill(&c); err != nil {
return nil, err
}
// If there is an azure.yaml, load it and return the services.
if _, err := os.Stat(c.azdContext.ProjectPath()); err == nil {
var cc struct {
projectConfig *project.ProjectConfig `container:"type"`
}
if err := container.Fill(&cc); err != nil {
return nil, err
}
appHost, err := appHostForProject(ctx, cc.projectConfig, c.dotnetCli)
if err != nil {
return nil, err
}
hostInfo := &AspireHost{
Name: filepath.Base(filepath.Dir(appHost.Path())),
Path: appHost.Path(),
}
manifest, err := apphost.ManifestFromAppHost(ctx, appHost.Path(), c.dotnetCli, aspireEnv)
if err != nil {
return nil, fmt.Errorf("failed to load app host manifest: %w", err)
}
hostInfo.Services = servicesFromManifest(manifest)
return hostInfo, nil
} else if errors.Is(err, os.ErrNotExist) {
hosts, err := appdetect.DetectAspireHosts(ctx, c.azdContext.ProjectDirectory(), c.dotnetCli)
if err != nil {
return nil, fmt.Errorf("failed to discover app host project under %s: %w", c.azdContext.ProjectPath(), err)
}
if len(hosts) == 0 {
return nil, fmt.Errorf("no app host projects found under %s", c.azdContext.ProjectPath())
}
if len(hosts) > 1 {
return nil, fmt.Errorf("multiple app host projects found under %s", c.azdContext.ProjectPath())
}
hostInfo := &AspireHost{
Name: filepath.Base(filepath.Dir(hosts[0].Path)),
Path: hosts[0].Path,
}
manifest, err := apphost.ManifestFromAppHost(ctx, hosts[0].Path, c.dotnetCli, aspireEnv)
if err != nil {
return nil, fmt.Errorf("failed to load app host manifest: %w", err)
}
hostInfo.Services = servicesFromManifest(manifest)
return hostInfo, nil
} else {
return nil, fmt.Errorf("failed to stat project path: %w", err)
}
}
// RenameAspireHostAsync is the server implementation of:
// ValueTask RenameAspireHostAsync(Session session, string newPath, CancellationToken cancellationToken).
func (s *aspireService) RenameAspireHostAsync(
ctx context.Context, rc RequestContext, newPath string, observer IObserver[ProgressMessage],
) error {
_, err := s.server.validateSession(ctx, rc.Session)
if err != nil {
return err
}
// TODO(azure/azure-dev#3283): What should this do? Rewrite azure.yaml? We'll end up losing comments...
return errors.New("not implemented")
}
// ServeHTTP implements http.Handler.
func (s *aspireService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
serveRpc(w, r, map[string]Handler{
"GetAspireHostAsync": HandlerFunc3(s.GetAspireHostAsync),
"RenameAspireHostAsync": HandlerAction3(s.RenameAspireHostAsync),
})
}