forked from juju/juju
/
repofactory.go
117 lines (97 loc) · 3.08 KB
/
repofactory.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
// Copyright 2021 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package services
import (
"sync"
"github.com/juju/errors"
"github.com/juju/loggo"
"github.com/DavinZhang/juju/charmhub"
corecharm "github.com/DavinZhang/juju/core/charm"
charmrepo "github.com/DavinZhang/juju/core/charm/repository"
"github.com/DavinZhang/juju/core/logger"
)
// CharmRepoFactoryConfig encapsulates the information required for creating a
// new CharmRepoFactory instance.
type CharmRepoFactoryConfig struct {
// The logger to use.
Logger loggo.Logger
// A transport that is injected when making charmhub API calls.
Transport charmhub.Transport
StateBackend StateBackend
ModelBackend ModelBackend
}
// CharmRepoFactory instantitates charm repositories. It memoizes created
// repositories allowing them to be reused by subsequent GetCharmRepository
// calls.
type CharmRepoFactory struct {
logger loggo.Logger
charmhubTransport charmhub.Transport
stateBackend StateBackend
modelBackend ModelBackend
mu sync.Mutex
memoizedRepos map[corecharm.Source]corecharm.Repository
}
// NewCharmRepoFactory returns a new factory instance with the provided configuration.
func NewCharmRepoFactory(cfg CharmRepoFactoryConfig) *CharmRepoFactory {
return &CharmRepoFactory{
logger: cfg.Logger,
charmhubTransport: cfg.Transport,
stateBackend: cfg.StateBackend,
modelBackend: cfg.ModelBackend,
memoizedRepos: make(map[corecharm.Source]corecharm.Repository),
}
}
// GetCharmRepository returns a suitable corecharm.Repository instance for the
// requested source. Lookups are memoized for future requests.
func (f *CharmRepoFactory) GetCharmRepository(src corecharm.Source) (corecharm.Repository, error) {
f.mu.Lock()
defer f.mu.Unlock()
if repo, isCached := f.memoizedRepos[src]; isCached {
return repo, nil
}
var repo corecharm.Repository
switch src {
case corecharm.CharmStore:
controllerCfg, err := f.stateBackend.ControllerConfig()
if err != nil {
return nil, errors.Trace(err)
}
repo = charmrepo.NewCharmStoreRepository(
f.logger.Child("charmstorerepo"),
controllerCfg.CharmStoreURL(),
)
case corecharm.CharmHub:
cfg, err := f.modelBackend.Config()
if err != nil {
return nil, errors.Trace(err)
}
options := []charmhub.Option{
charmhub.WithHTTPTransport(func(charmhub.Logger) charmhub.Transport {
return f.charmhubTransport
}),
}
var chCfg charmhub.Config
chURL, ok := cfg.CharmHubURL()
if ok {
chCfg, err = charmhub.CharmHubConfigFromURL(chURL, f.logger, options...)
} else {
chCfg, err = charmhub.CharmHubConfig(f.logger, options...)
}
if err != nil {
return nil, errors.Trace(err)
}
chClient, err := charmhub.NewClient(chCfg)
if err != nil {
return nil, errors.Trace(err)
}
repo = charmrepo.NewCharmHubRepository(
f.logger.ChildWithLabels("charmhubrepo", logger.CHARMHUB),
chClient,
)
default:
return nil, errors.NotSupportedf("charm repository for source %q", src)
}
// Memoize for future lookups.
f.memoizedRepos[src] = repo
return repo, nil
}