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

Add support for deleting parent paths of matches #1

Merged
merged 9 commits into from
Sep 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21
check-latest: true
cache: true

Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19
go-version: 1.21
check-latest: true
cache: true

Expand Down
17 changes: 14 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
FROM releases-docker.jfrog.io/jfrog/jfrog-cli-v2-jf:2.27.1
# Build
FROM golang:1.21 AS build-stage

WORKDIR /app

COPY . ./
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux go build

# Deploy
FROM releases-docker.jfrog.io/jfrog/jfrog-cli-v2-jf:2.48.0

WORKDIR /root/
RUN mkdir -p .jfrog/plugins/
COPY rt-retention .jfrog/plugins/rt-retention

RUN mkdir -p .jfrog/plugins
COPY --from=build-stage /app/rt-retention .jfrog/plugins

ENTRYPOINT ["jf", "rt-retention"]
CMD ["--help"]
99 changes: 73 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,48 +35,46 @@ To enforce them, set up a humble cron job running the plugin.

- Options:
- --dry-run _do not delete artifacts [Default: **true**]_
- --verbose _output verbose logging [Default: false]_
- --recursive _recursively find FileSpecs files in the given dir [Default: false]_

#### expand

- Usage: `jf rt-retention expand [command options] <config-path> <templates-path> <output-path>`

- Arguments:
- config-path _(Path to the JSON config file)_
- templates-path _(Path to the templates dir)_
- output-path _(Path to output the generated FileSpecs)_

- Options:
- --verbose _output verbose logging [Default: false]_
- --recursive _recursively find templates in the given dir [Default: false]_

### running with verbose output

For verbose output to aid in debugging, set `JFROG_CLI_LOG_LEVEL=DEBUG`.

## Templating

The [`expand`](#expand) command can generate FileSpecs from Go templates, populated with values from a JSON config file.

The JSON config file contains a key for each template with an array of entries.
The keys should match the template file names (without the `.json` extension).
The JSON config file may contain one or more policy definitions.
Each specifies the template file it uses, as well as a list of entries.
The template file path should be relative to the config file.
Each entry will result in a FileSpecs file being generated.

_Example `config.json`:_
```json
{
"delete-everything": [
{
"Repo": "generic-tmp-local"
}
],
"delete-older-than": [
{
"Repo": "generic-dev-local",
"Time": "14d"
"my-junk-repositories": {
"template": "templates/entire-repo.json",
"entries": [
{ "Repo": "scratch-local" }
]
},
{
"Repo": "generic-rc-local",
"Time": "1y"
"my-dev-repositories": {
"template": "templates/older-than.json",
"entries": [
{ "Repo": "generic-dev-local", "Time": "3w" },
{ "Repo": "libs-snapshot-local", "Time": "1y" }
]
}
]
}
```

Expand Down Expand Up @@ -105,10 +103,59 @@ Pass the config file, the templates directory and the output directory to the [`

```bash
$ jf rt-retention expand config.json templates/ policies/
[🔵Info] Collecting template files
[🔵Info] Found 2 JSON files
[🔵Info] Parsing config file
[🔵Info] Expanding delete-everything
[🔵Info] Expanding delete-older-than
[🔵Info] Reading config file
[🔵Info] Parsing config JSON
[🔵Info] Expanding policies
[🔵Info] [ my-junk-repositories ]
[🔵Info] [ my-dev-repositories ]
[🔵Info] Done
```

### Extra templating properties

#### deleteParent

Policies can set `deleteParent` to delete the _parent paths_ of what the FileSpecs would match, rather than the matches themselves.

This is useful for deleting entire directories if they contain an artifact matching certain conditions, or deleting Docker images based on conditions on their manifest file.

```json
{
"template-one": {
"template": "templates/template.json",
"deleteParent": true,
"entries": [
{ "Repo": "scratch-local" }
]
}
}
```

#### nameProperty

Policies can optionally set a `nameProperty`, which can be used to change the generated FileSpecs' filename to the value of the given property key.
Without it, FileSpecs are generated using the name of the template, and the index of their entry.

The below example uses the `Repo` property value to use as the FileSpecs' filename.

```json
{
"template-one": {
"template": "templates/template.json",
"nameProperty": "Repo",
"entries": [
{ "Repo": "scratch-local" },
{ "Repo": "dev-local" }
]
}
}
```

Expanding the templates will result in the following generated files:

```
output/
`- template-one/
|- scratch-local-0.json
`- dev-local-0.json
```
57 changes: 57 additions & 0 deletions commands/artifactory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package commands

import (
"errors"

core_utils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils"
"github.com/jfrog/jfrog-cli-core/v2/common/commands"
"github.com/jfrog/jfrog-cli-core/v2/plugins/components"
"github.com/jfrog/jfrog-cli-core/v2/utils/config"
"github.com/jfrog/jfrog-client-go/artifactory"
client_utils "github.com/jfrog/jfrog-client-go/utils"
"github.com/jfrog/jfrog-client-go/utils/log"
)

func GetArtifactoryDetails(context *components.Context) (*config.ServerDetails, error) {
log.Info("Fetching Artifactory details")

var servers = commands.GetAllServerIds()
log.Debug("Server IDs: ", len(servers))
for _, server := range servers {
log.Debug("\t", server)
}

details, cfgErr := config.GetDefaultServerConf()
if cfgErr != nil {
return nil, cfgErr
}

log.Debug("Default server ID:")
log.Debug("\t", details.ServerId, "(", details.ArtifactoryUrl, ")")

if details.ArtifactoryUrl == "" {
return nil, errors.New("no server-id was found, or the server-id has no url")
}

details.ArtifactoryUrl = client_utils.AddTrailingSlashIfNeeded(details.ArtifactoryUrl)
if tokenErr := config.CreateInitialRefreshableTokensIfNeeded(details); tokenErr != nil {
return nil, tokenErr
}

return details, nil
}

func GetArtifactoryManager(context *components.Context, dryRun bool) (artifactory.ArtifactoryServicesManager, error) {
artifactoryDetails, cfgErr := GetArtifactoryDetails(context)
if cfgErr != nil {
return nil, cfgErr
}

log.Info("Configuring Artifactory manager")
artifactoryManager, rtfErr := core_utils.CreateServiceManager(artifactoryDetails, 3, 5000, dryRun)
if rtfErr != nil {
return nil, rtfErr
}

return artifactoryManager, nil
}
Loading