Skip to content

Commit

Permalink
Update custom images when application is updated
Browse files Browse the repository at this point in the history
Signed-off-by: gatici <[email protected]>
  • Loading branch information
gatici committed Jun 2, 2024
1 parent 8205744 commit 1dd730a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 53 deletions.
116 changes: 63 additions & 53 deletions internal/juju/applications.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const (
)

const (
// HeaderContentType is the header name for the type of a file upload.
// HeaderContentType is the header name for the type of file upload.
HeaderContentType = "Content-Type"
// HeaderContentSha384 is the header name for the sha hash of a file upload.
HeaderContentSha384 = "Content-Sha384"
Expand Down Expand Up @@ -448,7 +448,7 @@ func (c applicationsClient) CreateApplication(ctx context.Context, input *Create
if applicationAPIClient.BestAPIVersion() >= 19 {
err = c.deployFromRepository(applicationAPIClient, resourceHttpClient, transformedInput)
} else {
err = c.legacyDeploy(ctx, conn, applicationAPIClient, transformedInput, resourceHttpClient)
err = c.legacyDeploy(ctx, conn, applicationAPIClient, transformedInput)
err = jujuerrors.Annotate(err, "legacy deploy method")
}
if err != nil {
Expand Down Expand Up @@ -502,7 +502,7 @@ func (c applicationsClient) deployFromRepository(applicationAPIClient *apiapplic
// Remove the funcationality associated with legacyDeploy
// once the provider no longer supports a version of juju
// before 3.3.
func (c applicationsClient) legacyDeploy(ctx context.Context, conn api.Connection, applicationAPIClient *apiapplication.Client, transformedInput transformedCreateApplicationInput, resourceHttpClient *HttpRequestClient) error {
func (c applicationsClient) legacyDeploy(ctx context.Context, conn api.Connection, applicationAPIClient *apiapplication.Client, transformedInput transformedCreateApplicationInput) error {
// Version needed for operating system selection.
c.controllerVersion, _ = conn.ServerVersion()

Expand Down Expand Up @@ -621,7 +621,7 @@ func (c applicationsClient) legacyDeploy(ctx context.Context, conn api.Connectio
Origin: resultOrigin,
}

resources, err := c.processResources(charmsAPIClient, conn, charmID, transformedInput.applicationName, transformedInput.resources, resourceHttpClient)
resources, err := c.processResources(charmsAPIClient, conn, charmID, transformedInput.applicationName, transformedInput.resources)
if err != nil && !jujuerrors.Is(err, jujuerrors.AlreadyExists) {
return err
}
Expand Down Expand Up @@ -832,7 +832,7 @@ func splitCommaDelimitedList(list string) []string {

// processResources is a helper function to process the charm
// metadata and request the download of any additional resource.
func (c applicationsClient) processResources(charmsAPIClient *apicharms.Client, conn api.Connection, charmID apiapplication.CharmID, appName string, resources map[string]string, resourceHttpClient *HttpRequestClient) (map[string]string, error) {
func (c applicationsClient) processResources(charmsAPIClient *apicharms.Client, conn api.Connection, charmID apiapplication.CharmID, appName string, resources map[string]string) (map[string]string, error) {
charmInfo, err := charmsAPIClient.CharmInfo(charmID.URL)
if err != nil {
return nil, typedError(err)
Expand All @@ -848,7 +848,7 @@ func (c applicationsClient) processResources(charmsAPIClient *apicharms.Client,
return nil, err
}

return addPendingResources(appName, charmInfo.Meta.Resources, resources, charmID, resourcesAPIClient, resourceHttpClient)
return addPendingResources(appName, charmInfo.Meta.Resources, resources, charmID, resourcesAPIClient)
}

// ReadApplicationWithRetryOnNotFound calls ReadApplication until
Expand Down Expand Up @@ -1470,65 +1470,74 @@ func (c applicationsClient) updateResources(appName string, resources map[string
return nil, nil
}

return addPendingResources(appName, filtered, resources, charmID, resourcesAPIClient, resourceHttpClient)
return addPendingResources(appName, filtered, resources, charmID, resourcesAPIClient)
}

func addPendingResources(appName string, resourcesToBeAdded map[string]charmresources.Meta, resourcesRevisions map[string]string,
charmID apiapplication.CharmID, resourcesAPIClient ResourceAPIClient, resourceHttpClient *HttpRequestClient) (map[string]string, error) {
pendingResources := []charmresources.Resource{}
pendingResourceUploads := []apiapplication.PendingResourceUpload{}
charmID apiapplication.CharmID, resourcesAPIClient ResourceAPIClient) (map[string]string, error) {
pendingResourcesforAdd := []charmresources.Resource{}
toReturn := map[string]string{}

for _, resourceMeta := range resourcesToBeAdded {
aux := charmresources.Resource{
Meta: resourceMeta,
Origin: charmresources.OriginStore,
Revision: -1,
}
if resourcesRevisions != nil {
if revision, ok := resourcesRevisions[resourceMeta.Name]; ok {
if isInt(revision) {
iRevision, err := strconv.Atoi(revision)
if deployValue, ok := resourcesRevisions[resourceMeta.Name]; ok {
if isInt(deployValue) {
// A resource revision is provided
providedRev, err := strconv.Atoi(deployValue)
if err != nil {
return nil, typedError(err)
}
aux := charmresources.Resource{
Meta: resourceMeta,
Origin: charmresources.OriginStore,
Revision: -1,
}
aux.Revision = providedRev
pendingResourcesforAdd = append(pendingResourcesforAdd, aux)
} else {
// A new resource to be uploaded by the client
uux := charmresources.Resource{
Meta: resourceMeta,
Origin: charmresources.OriginUpload,
}

fileSystem := osFilesystem{}
t, typeParseErr := charmresources.ParseType(resourceMeta.Type.String())
if typeParseErr != nil {
return nil, typedError(typeParseErr)
}
r, openResErr := resourcecmd.OpenResource(deployValue, t, fileSystem.Open)
if openResErr != nil {
return nil, typedError(openResErr)
}
toRequestUpload, err := resourcesAPIClient.UploadPendingResource(appName, uux, deployValue, r)
if err != nil {
return nil, typedError(err)
}
aux.Revision = iRevision
// Add the resource name and the corresponding UUID to the resources map
toReturn[resourceMeta.Name] = toRequestUpload
}
pendingResourceUploads = append(pendingResourceUploads, apiapplication.PendingResourceUpload{
Name: resourceMeta.Name,
Filename: resourcesRevisions[resourceMeta.Name],
Type: resourceMeta.Type.String(),
})
}
}

pendingResources = append(pendingResources, aux)
}

resourcesReq := apiresources.AddPendingResourcesArgs{
ApplicationID: appName,
CharmID: apiresources.CharmID{
URL: charmID.URL,
Origin: charmID.Origin,
},
Resources: pendingResources,
}

toRequest, err := resourcesAPIClient.AddPendingResources(resourcesReq)
if err != nil {
return nil, typedError(err)
}

fileSystem := osFilesystem{}
uploadErr := uploadExistingPendingResources(appName, pendingResourceUploads, fileSystem, resourceHttpClient)

if uploadErr != nil {
return nil, uploadErr
}

// now build a map with the resource name and the corresponding UUID
toReturn := map[string]string{}
for i, argsResource := range pendingResources {
toReturn[argsResource.Meta.Name] = toRequest[i]
if len(pendingResourcesforAdd) != 0 {
resourcesReqforAdd := apiresources.AddPendingResourcesArgs{
ApplicationID: appName,
CharmID: apiresources.CharmID{
URL: charmID.URL,
Origin: charmID.Origin,
},
Resources: pendingResourcesforAdd,
}
toRequestAdd, err := resourcesAPIClient.AddPendingResources(resourcesReqforAdd)
if err != nil {
return nil, typedError(err)
}
// Add the resource name and the corresponding UUID to the resources map
for i, argsResource := range pendingResourcesforAdd {
toReturn[argsResource.Meta.Name] = toRequestAdd[i]
}
}

return toReturn, nil
Expand All @@ -1547,7 +1556,7 @@ func upload(appName, name, filename, pendingID string, reader io.ReadSeeker, res
if err != nil {
return jujuerrors.Trace(err)
}
var response params.UploadResult // ignored
var response params.UploadResult
if err := resourceHttpClient.httpClient.Do(resourceHttpClient.facade.RawAPICaller().Context(), req, &response); err != nil {
return jujuerrors.Trace(err)
}
Expand Down Expand Up @@ -1603,6 +1612,7 @@ func uploadExistingPendingResources(
if pendingResources == nil {
return nil
}
pendingID := ""

for _, pendingResUpload := range pendingResources {
t, typeParseErr := charmresources.ParseType(pendingResUpload.Type)
Expand All @@ -1615,7 +1625,7 @@ func uploadExistingPendingResources(
if openResErr != nil {
return jujuerrors.Annotatef(openResErr, "unable to open resource %v", pendingResUpload.Name)
}
uploadErr := upload(appName, pendingResUpload.Name, pendingResUpload.Filename, "", r, resourceHttpClient)
uploadErr := upload(appName, pendingResUpload.Name, pendingResUpload.Filename, pendingID, r, resourceHttpClient)

if uploadErr != nil {
return jujuerrors.Trace(uploadErr)
Expand Down
3 changes: 3 additions & 0 deletions internal/juju/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package juju

import (
"github.com/juju/charm/v12"
charmresources "github.com/juju/charm/v12/resource"
"github.com/juju/juju/api"
apiapplication "github.com/juju/juju/api/client/application"
apiclient "github.com/juju/juju/api/client/client"
Expand All @@ -17,6 +18,7 @@ import (
"github.com/juju/juju/core/secrets"
"github.com/juju/juju/rpc/params"
"github.com/juju/names/v5"
"io"
)

type SharedClient interface {
Expand Down Expand Up @@ -63,6 +65,7 @@ type ModelConfigAPIClient interface {
type ResourceAPIClient interface {
AddPendingResources(args apiresources.AddPendingResourcesArgs) ([]string, error)
ListResources(applications []string) ([]resources.ApplicationResources, error)
UploadPendingResource(applicationID string, resource charmresources.Resource, filename string, r io.ReadSeeker) (id string, err error)
}

type SecretAPIClient interface {
Expand Down
17 changes: 17 additions & 0 deletions internal/juju/mock_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1dd730a

Please sign in to comment.