Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(application): deploy applications with custom resources #493

Merged
merged 27 commits into from
Aug 27, 2024

Conversation

gatici
Copy link
Contributor

@gatici gatici commented May 30, 2024

Description

This PR provides to use custom (OCI image) charm resources with applications. The application resource could be a charm revision or a custom OCI image which needs to be pulled from a repository. The following "juju_application" resource definition becomes valid within this PR. This PR both works with all the Juju versions which are supported by Juju Terraform provider. (Tested with Juju 2.9.x and 3.4.x versions)

resource "juju_application" "ausf" {
  name = "ausf"
  model = var.model_name

  charm {
    name = "sdcore-ausf-k8s"
    channel = var.channel
  }
  resources = {
      ausf-image = "gatici/sdcore-ausf:1.4.0"
      // ausf-image =  "2"
  }
  units = 1
  trust = true
}

Design Spec: https://docs.google.com/document/d/1i236ntmw-qXyqifmEtk_rcszWXcXSUhXkeJ6ByKXIeE/edit

Fixes: #460

Type of change

  • Change existing resource
  • Change in the tests (one or several tests have been changed)
  • Requires a documentation update

Environment

The following steps are performed to prepare the environment.

Install Microk8s:

sudo snap install microk8s --channel=1.29-strict/stable
sudo usermod -a -G snap_microk8s $USER
newgrp snap_microk8s
sudo microk8s enable hostpath-storage

Install Juju:

sudo snap install juju --channel=3.4/stable
juju bootstrap microk8s

Install Terraform:

sudo snap install --classic terraform

Create terraformrc file with following contents. Write the path of terraform.d/plugins directory if it is in a different path.

touch .terraformrc 
provider_installation {
  filesystem_mirror {
    path = "~/.terraform.d/plugins"
    include = ["juju/juju"]
  }
  direct {
    exclude = ["juju/juju"]
  }
}

QA steps

Manual QA steps should be done to test this PR.

Create a folder to store the Terraform files for testing.

mkdir testing
cd testing

Create a main.tf file with following contents:

resource "juju_application" "ausf" {
  name = "ausf"
  model = var.model_name

  charm {
    name = "sdcore-ausf-k8s"
    channel = var.channel
  }
  resources = {
      ausf-image = "gatici/sdcore-ausf:1.4.0"
  }
  units = 1
  trust = true
}

Create a terraform.tf file with following contents:

terraform {
  required_providers {
    juju = {
      source  = "juju/juju"
      version = "0.12.0"
    }
  }
}

Create a terraform.tfvars file with following contents:

model_name ="test40"

Create a variables.tf file with following contents:

variable "model_name" {
  description = "Name of Juju model to deploy application to."
  type        = string
  default     = ""
}

variable "channel" {
  description = "The channel to use when deploying a charm."
  type        = string
  default     = "1.4/edge"
}

variable "db_application_name" {
  description = "The name of the application providing the `database` endpoint."
  type        = string
  default     = "mongodb-k8s"
}

variable "certs_application_name" {
  description = "Name of the application providing the `certificates` integration endpoint."
  type = string
  default = "self-signed-certificates"
}

variable "nrf_application_name" {
  description = "The name of the application providing the `fiveg_nrf` endpoint."
  type        = string
  default     = "nrf"
}

Fetch the PR and run following commads to install it.

make go-install
make install

Create a juju model:

juju add-model test40

Initialise the provider:

terraform init

Run Terraform plan by providing a var-file:

terraform plan -var-file="terraform.tfvars" 

Deploy the application:

terraform apply -auto-approve 

Check the pod to see the attached image.

microk8s.kubectl describe pod ausf-0 -n test40

Additional notes

Test with changing the resources part with different image versions.

Using a revision as string:

resources = {
      ausf-image = "30"
}

@gatici gatici marked this pull request as draft May 30, 2024 01:15
@gatici gatici marked this pull request as ready for review May 30, 2024 21:11
@gatici gatici marked this pull request as draft June 2, 2024 05:29
@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from 3083ece to 1dd730a Compare June 2, 2024 06:45
@gatici gatici marked this pull request as ready for review June 2, 2024 06:50
@cderici cderici added this to the 0.13.0 milestone Jun 3, 2024
Copy link
Member

@hmlanigan hmlanigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your contribution. It's a good start.

To proceed, please read and follow the process defined: https://github.com/juju/terraform-provider-juju/wiki/Developing#planning--design

Please also include description of what happens during the following scenarios.

  • deploy
  • refresh
  • the resource element is removed from the plan
  • what happens if the file isn't an image location?
  • what happens if the value is changed from an int to a file?
  • what happens if the value is changed from a file to an int?

@hmlanigan hmlanigan removed this from the 0.13.0 milestone Jun 6, 2024
@gatici
Copy link
Contributor Author

gatici commented Jun 12, 2024

Thank you for your contribution. It's a good start.

To proceed, please read and follow the process defined: https://github.com/juju/terraform-provider-juju/wiki/Developing#planning--design

Please also include description of what happens during the following scenarios.

* deploy

* refresh

* the resource element is removed from the plan

* what happens if the file isn't an image location?

* what happens if the value is changed from an int to a file?

* what happens if the value is changed from a file to an int?

Hello @hmlanigan,
The behaviour is summarized below. Please tell me if there is something undesired.

  * If the plan does not specify a resource and resources are added to the plan (as a revision number or a custom resource), specified resources are attached to the application (equivalent to juju attach-resource).
  * If the plan does specify resource revisions and if the charm revision or channel is updated, existing resources are kept.  (Resources are not detached)
  * If the plan does specify resource revisions and resources are removed from the plan:
          - If charm revision/channel is updated, the resources associated with the updated charm revision or channel  is attached.
          - If the charm revision/channel are not updated then the resources associated with the existing charm revision/channel are attached.
  * Charm could be deployed without resource, then resource could be  added later.
  * Resources could be provided in the following formats:
          - A custom repository URL
          - A files ends with .txt, .json  or .yaml
          - A resource revision from CharmHub
    * Charm could be deployed with resources.
    * If the provided resource revision does not exist during initial deployment or update, Client does not start deployment with an error that resource was not found in the store.
    * If the provided custom resource does not exist during initial deployment or update, Client  start deployment and charm could not be deployed properly and charm will be in error state.
    *  If the Provided resource type is not correct then Client fails with incorrect resource error for below scenarios:
          - An image is expected but file does not include image URL
          - A plain text file is expected but a json or yaml file is provided including image URL.
    *  If the provided resource does not exist then Client fails with path is not valid error.
    *  Changing resources from a file to an int or string does not create any problem. Resources are processed smoothly.
        -  If provided resource value is changed from an int to a file  then the image resource from the file is attached.
        -  If provided resource value is changed from a file to an int then image revision is attached.

@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from 60c62dd to 59c5c91 Compare June 12, 2024 21:30
@hmlanigan hmlanigan self-requested a review June 22, 2024 11:55
@hmlanigan
Copy link
Member

hmlanigan commented Jun 22, 2024

  • If the plan does not specify a resource and resources are added to the plan (as a revision number or a custom resource), specified resources are attached to the application (equivalent to juju attach-resource).
  • If the plan does specify resource revisions and if the charm revision or channel is updated, existing resources are kept. (Resources are not detached)

This is counter to current juju behavior. Today juju will upgrade the resources with the charm if a new resource is available, provided that the resource is not an attached local file (but not an ici-image).

This behavior would have to be explicitly implemented if we want it. It'd require a juju change.

Resources can never be detached by juju.

  • If the plan does specify resource revisions and resources are removed from the plan:
    - If charm revision/channel is updated, the resources associated with the updated charm revision or channel is attached.
    - If the charm revision/channel are not updated then the resources associated with the existing charm revision/channel are attached.

A charm revision may be in more than one channel. The last I knew resources are associated with a channel only today, not a charm revision.

  • Charm could be deployed without resource, then resource could be added later.

Juju will not allow a charm with resources to be deployed without one unless the process errors. If no resource is specified, juju deploy will find the resources in charm hub and use those.

  • Resources could be provided in the following formats:
    - A custom repository URL

What is contained in this repository?

      - A files ends with .txt, .json  or .yaml

We will only be allowing revision number and oci-image information be used. We will not support custom files to be uploaded.

      - A resource revision from CharmHub
* Charm could be deployed with resources.
* If the provided resource revision does not exist during initial deployment or update, Client does not start deployment with an error that resource was not found in the store.

What will only work for versions of juju where DeployFromRepostory isn't used in older versions of juju.

* If the provided custom resource does not exist during initial deployment or update, Client  start deployment and charm could not be deployed properly and charm will be in error state.

This is dependent on the charms behavior.

*  If the Provided resource type is not correct then Client fails with incorrect resource error for below scenarios:
      - An image is expected but file does not include image URL
      - A plain text file is expected but a json or yaml file is provided including image URL.
*  If the provided resource does not exist then Client fails with path is not valid error.
*  Changing resources from a file to an int or string does not create any problem. Resources are processed smoothly.

The wording here is tricky. This will only work for oci-image resources. Once you have a file resource using a local upload you can never go back to the revisions numbers. However we will not be supporting local upload of a file resource with terraform.

    -  If provided resource value is changed from an int to a file  then the image resource from the file is attached.
    -  If provided resource value is changed from a file to an int then image revision is attached.

How hard is it to always provide a link to an image rather than handling the data in a file? e.g.

--resource \
     demo-server-image=ghcr.io/canonical/api_demo_server:1.0.1

@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from cc90a12 to 2b8c852 Compare July 2, 2024 08:25
@gatici
Copy link
Contributor Author

gatici commented Jul 2, 2024

The review comments are addressed. The resources are updated to latest revision associated with the charm channel upon channel updates. As summarized below, only image resources could be provided as custom resource inputs. Image information could be written directly in a string format or provided in a json or yaml file. This PR both works with deployFromRepository and legacyDeploy methods, so older Juju versions are supported.

Charms could be deployed with specifying the resources (from CharmHub or an OCI image repository). 
If the resources are not specified, the resources which are associated with the Charm in the CharmHub are used. 
Resource inputs are provided in a string format.
-         Resource revision number from CharmHub (string)
-         OCI image information as a URL (string)
-         A path of json or yaml file which includes OCI image repository information (string)

Changing resource input from a revision to a custom OCI resource is processed and updated smoothly according to the provided input.

Resources could be added to the Terraform plan after deployment.
-         If the resources are added to the plan (as a revision number or a custom OCI image resource), specified resources are attached to the application (equivalent to juju attach-resource).

Charm which includes resources could be updated. If the plan does specify resource revisions from CharmHub:
-         if the charm channel is updated, resources get updated to the latest revision associated with the updated channel. If the plan does specify custom OCI image resources:
-         if the charm channel is updated, existing resources are kept. (Resources are not detached)

Resources could be removed from the Terraform plan. If the plan does specify resource revisions from CharmHub or custom OCI images, then resources are removed from the plan:
-         If the charm channel is updated, resources get updated to the latest revision associated with the updated charm channel.
-         If the charm channel is not updated then the resources get updated to the latest revision associated with the existing charm channel.

@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from 2b8c852 to 4acc5b8 Compare July 2, 2024 15:30
Copy link
Member

@hmlanigan hmlanigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm part way through my review. However I've run out of time to complete it, this is what I have now. I had to spend some time refreshing my knowledge of how juju handles resources, it's a complex bit of code.

I see no need to add the json or yaml file option for oci-images as they can be directly listed in the plan as a URL. It also muddies the water around uploading file resources which we do not intend to support.

examples/resources/juju_application/resource.tf Outdated Show resolved Hide resolved
internal/provider/validator_base.go Outdated Show resolved Hide resolved
internal/provider/resource_application.go Outdated Show resolved Hide resolved
internal/provider/provider_test.go Outdated Show resolved Hide resolved
internal/provider/resource_machine_test.go Outdated Show resolved Hide resolved
internal/provider/resource_application.go Outdated Show resolved Hide resolved
internal/provider/resource_application.go Show resolved Hide resolved
internal/provider/resource_application.go Outdated Show resolved Hide resolved
internal/juju/applications.go Outdated Show resolved Hide resolved
internal/juju/applications.go Outdated Show resolved Hide resolved
@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from 9d89021 to 12f19e7 Compare July 8, 2024 09:32
@jujubot
Copy link
Contributor

jujubot commented Jul 24, 2024

Thanks for opening a pull request! Please follow the instructions here to ensure your pull request is ready for review. Then, a maintainer will review your patch.

@hpidcock @anvial

1 similar comment
@jujubot
Copy link
Contributor

jujubot commented Jul 24, 2024

Thanks for opening a pull request! Please follow the instructions here to ensure your pull request is ready for review. Then, a maintainer will review your patch.

@hpidcock @anvial

@gatici gatici changed the title feat: Deploy applications with custom resources feat(application): Deploy applications with custom resources Jul 25, 2024
@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch 2 times, most recently from 2106a84 to 749290a Compare July 25, 2024 17:37
Copy link
Member

@hmlanigan hmlanigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are my current comments, though I haven't completed the review yet.

Mostly polish and nitpicks with 2 main questions/concerns. One is about not using the juju api resource client directly and the other is related to the validator logic. More detail with the lines.

Some of the changes are to make the code more consistent with already existing code style.

P.S I'm trying out using https://conventionalcomments.org

internal/provider/validator_resourcekey.go Outdated Show resolved Hide resolved
internal/provider/validator_resourcekey_test.go Outdated Show resolved Hide resolved
internal/juju/resources.go Show resolved Hide resolved
internal/juju/resources_test.go Outdated Show resolved Hide resolved
internal/provider/resource_application.go Outdated Show resolved Hide resolved
internal/provider/validator_resourcekey.go Outdated Show resolved Hide resolved
internal/provider/validator_resourcekey.go Outdated Show resolved Hide resolved
internal/provider/validator_resourcekey_test.go Outdated Show resolved Hide resolved
internal/provider/validator_resourcekey.go Outdated Show resolved Hide resolved
Copy link
Member

@hmlanigan hmlanigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA went well with both k8s and machine charms and their resources.

internal/provider/resource_application.go Outdated Show resolved Hide resolved
@gatici
Copy link
Contributor Author

gatici commented Aug 2, 2024

Here are my current comments, though I haven't completed the review yet.

Mostly polish and nitpicks with 2 main questions/concerns. One is about not using the juju api resource client directly and the other is related to the validator logic. More detail with the lines.

Some of the changes are to make the code more consistent with already existing code style.

P.S I'm trying out using https://conventionalcomments.org

Hello Heather,

I have addressed some of the comments but some of them are still open. I will continue on Monday.
As you suggested in your review, new added ResourceHttpClient is removed. I figured out how to use Juju Resource API client for initial deployment stage. This required some additional info from charm and some helper methods are added under resources.go.

Regarding with the validator, I appreciate for your comments. I tried to improve the logic. I will also add the test cases for each scenario.

@hmlanigan hmlanigan self-requested a review August 5, 2024 20:05
@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch 2 times, most recently from 1bd1220 to af21bc2 Compare August 6, 2024 12:59
@hmlanigan hmlanigan self-requested a review August 12, 2024 15:32
gatici added 23 commits August 27, 2024 19:19
In the previous commits, a new sample TF plan was added
to show the usage of custom resources.
This commits reverts this change by adding combining the
placement and resource usage example in the same existing TF plan.

Signed-off-by: gatici <[email protected]>
ProviderStableVersion is changed while performing some
local tests mistakenly. This change is reverted with this commit.

Signed-off-by: gatici <[email protected]>
Empty lines are required between different types of imports
and these are added within this commit.

Signed-off-by: gatici <[email protected]>
Resolving the merge conflicts with main branch as
another merged PRs created some conflicts.

Signed-off-by: gatici <[email protected]>
This commit reorganizes the resourceKeyMarkdownDescription
by simplifying the explanation.

Signed-off-by: gatici <[email protected]>
This PR adds new functions to upload OCI images and handle upload
requests. In the initial commit, all these functions were
added to the `applications.go` file which reduces the readability of code.
This commit puts all the functions which are used to process
OCI image resources in a separate file named `resources.go'
to reduce the complexity and increase the readilibity.

docs(application): Application documentation is updated by adding
custom resource usage in the existing sample TF plan.
Application optional TF plan parameters are updated
by changing the description of `resources` map.

test(resources): A few tests are added for the functions in
the resources.go. This tests will be expanded in the next commits.

Signed-off-by: gatici <[email protected]>
We would like to indicate that default revision number from the
CharmHub should be used by providing an invalid revision number.
Formerly "0" was used but this is now fixed by replacing
it with "-1" in this commit.

Signed-off-by: gatici <[email protected]>
ResourceKey schema is validated using a custom PlanValidator named
StringIsResourceKeyValidator to to ensure that the string is an
int or OCI image information as a URL.
This will allow for failure during the planning phase if the
values are not as expected.

Signed-off-by: gatici <[email protected]>
…nd processResources functions

This commit renames the arguments in two functions as existing arguments does
not identify the correct resource types withing this change.:
- func processResources:
  - resources  -> resourcesToUse
    Argument "resources" are too generic and it is renamed to resourcesToUse.

- In addPendingResources:
  - resourcesToBeAdded -> charmResources
    resourcesToBeAdded indicates the resources which are available
    in the charm.Hence charmResources are used to indicate this map.
  - resourcesRevisions -> resourcesToUse
    resourceRevisions does not cover the OCI resources, however this map
    could include resource revisions from CharmHub and custom OCI images.

Signed-off-by: gatici <[email protected]>
…adibility

In ReadApplication method, rename resourceRevisions to usedResources

chore: Delete unnecassary configuration files which are planned
to used provider testing

Signed-off-by: gatici <[email protected]>
The mistalenly disabled lines are enabled.

Signed-off-by: gatici <[email protected]>
The PR was parked for a long time and provider stable version is
updated in the main branch during this time period.
We need to use the same provider version.

Signed-off-by: gatici <[email protected]>
from Charmhub if a resource revision is provided

If a revision is provided and application channel is updated,
provided revision number is used in the application.

docs(resources): Update the ResourceKey description in the Markdown file

chore: Improve the implementation of isInt method

Signed-off-by: gatici <[email protected]>
…epository URL format

Images are provided in allowed URL pattern and it is
validated using regex format.
Juju APIs can not resolve the image provided in digest
format so this format is not allowed.

Signed-off-by: gatici <[email protected]>
Debug mode is set to True during development and
mistakenly committed. This change is reverted.

Signed-off-by: gatici <[email protected]>
docs: Fixing typos and wrong content in method docstrings
chore: Updating and adding license header files
feat(resource): Remove new added ResourceHttpClient and use existing
Juju resourcesAPIClient.
To use Juju resourcesAPIClient some additional Charm info required and
helper methods are added to under resources.go.
chore: Unnecessary spaces are removed.
fix: Comments are addressed in validator resourcekey file to increase
the readability.

Signed-off-by: gatici <[email protected]>
Format the definition to fix the awkwardly reading and make it
compatible with Spec:
https://docs.google.com/document/d/1i236ntmw-qXyqifmEtk_rcszWXcXSUhXkeJ6ByKXIeE/edit.

Signed-off-by: gatici <[email protected]>
refactor: StringIsResourceKeyValidator ValidateMap function is
refactored to increase the readibility.

Signed-off-by: gatici <[email protected]>
fix(resources): Fix the helper methods to get the base or series
if none of them explicitly provided.

Signed-off-by: gatici <[email protected]>
and legacyDeploy methods

feat: Use ResourceAPIClient.Upload to upload the custom resources
for the applications which are deployed with deployFromRepository method
tests: Use grafana-k8s charm to validate the custom resource usage
in the integration tests

Signed-off-by: gatici <[email protected]>
tests: add more unit tests for addPendingResource and UploadPendingResource methods
fix: solve inregratation test and linting issues

Signed-off-by: gatici <[email protected]>
@gatici gatici force-pushed the Deploy-applications-with-custom-resources branch from 0a004b1 to a8acb4c Compare August 27, 2024 16:20
Copy link
Member

@hmlanigan hmlanigan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! merging now.

@hmlanigan
Copy link
Member

/merge

@hmlanigan
Copy link
Member

The failing integration tests are timing out for taking too long. There will shortly be a PR to help with this.

@jujubot jujubot merged commit 2f6bf74 into juju:main Aug 27, 2024
23 of 27 checks passed
@hmlanigan hmlanigan added this to the 0.13.1 milestone Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deploy charms using custom images
6 participants