/
resource.go
134 lines (116 loc) · 3.83 KB
/
resource.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
// Copyright 2016 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package deployer
import (
"strconv"
charmresource "github.com/juju/charm/v12/resource"
"github.com/juju/errors"
"github.com/juju/juju/api/base"
"github.com/juju/juju/api/client/application"
"github.com/juju/juju/api/client/resources"
resourcecmd "github.com/juju/juju/cmd/juju/resource"
"github.com/juju/juju/cmd/modelcmd"
)
// DeployResourcesFunc is the function type of DeployResources.
type DeployResourcesFunc func(
applicationID string,
chID resources.CharmID,
filesAndRevisions map[string]string,
resources map[string]charmresource.Meta,
conn base.APICallCloser,
filesystem modelcmd.Filesystem,
) (ids map[string]string, err error)
// DeployResources uploads the bytes for the given files to the server and
// creates pending resource metadata for the all resource mentioned in the
// metadata. It returns a map of resource name to pending resource IDs.
func DeployResources(
applicationID string,
chID resources.CharmID,
filesAndRevisions map[string]string,
// for refresh, current resources are added here.
res map[string]charmresource.Meta,
conn base.APICallCloser,
filesystem modelcmd.Filesystem,
) (ids map[string]string, err error) {
if len(filesAndRevisions)+len(res) == 0 {
// Nothing to upload.
return nil, nil
}
apiClient, err := resources.NewClient(conn)
if err != nil {
return nil, errors.Trace(err)
}
filenames := make(map[string]string)
revisions := make(map[string]int)
for name, val := range filesAndRevisions {
rev, err := strconv.Atoi(val)
if err != nil {
filenames[name] = val
} else {
revisions[name] = rev
}
}
ids, err = resourcecmd.DeployResources(resourcecmd.DeployResourcesArgs{
ApplicationID: applicationID,
CharmID: chID,
ResourceValues: filenames,
Revisions: revisions,
ResourcesMeta: res,
Client: &deployClient{apiClient},
Filesystem: filesystem,
})
if err != nil {
return nil, errors.Trace(err)
}
return ids, nil
}
type deployClient struct {
*resources.Client
}
// AddPendingResources adds pending metadata for store-based resources.
func (cl *deployClient) AddPendingResources(applicationID string, chID resources.CharmID, res []charmresource.Resource) ([]string, error) {
return cl.Client.AddPendingResources(resources.AddPendingResourcesArgs{
ApplicationID: applicationID,
CharmID: chID,
Resources: res,
})
}
type UploadExistingPendingResourcesFunc func(appName string,
pendingResources []application.PendingResourceUpload,
conn base.APICallCloser,
filesystem modelcmd.Filesystem) error
// UploadExistingPendingResources uploads local resources. Used
// after DeployFromRepository, where the resources have been added
// to the controller.
// Called after AddApplication so no pending resource IDs are
// necessary, see juju attach for more examples.
func UploadExistingPendingResources(
appName string,
pendingResources []application.PendingResourceUpload,
conn base.APICallCloser,
filesystem modelcmd.Filesystem) error {
if pendingResources == nil {
return nil
}
resourceApiClient, err := resources.NewClient(conn)
if err != nil {
return errors.Trace(err)
}
for _, pendingResUpload := range pendingResources {
t, typeParseErr := charmresource.ParseType(pendingResUpload.Type)
if typeParseErr != nil {
return errors.Annotatef(typeParseErr, "invalid type %v for pending resource %v",
pendingResUpload.Type, pendingResUpload.Name)
}
r, openResErr := resourcecmd.OpenResource(pendingResUpload.Filename, t, filesystem.Open)
if openResErr != nil {
return errors.Annotatef(openResErr, "unable to open resource %v", pendingResUpload.Name)
}
uploadErr := resourceApiClient.Upload(appName,
pendingResUpload.Name, pendingResUpload.Filename, "", r)
if uploadErr != nil {
return errors.Trace(uploadErr)
}
}
return nil
}