Simple Artifactory plugin for total size of Artefacts in local repositories

I’ve done a little plugin I hope might be useful for others who would like to know what is the total size of artefacts stored by Artifactory in local repository.

The functionality is quite simple:

  1. You can obtain a size of a repository by sending a POST request to url: /artifactory/api/plugins/execute/getRepositorySize?params=repoName=repository-name
  2. You can obtain a report in a form of a JSON Array for all local repositories by sending a POST request to url: /artifactory/api/plugins/execute/getAllRepositorySizes

Plugin code and a sample JSON response for all repository sizes below.

Just want to add that JFrog did a brilliant work with their very simple and elegant Artifactory API.

import org.artifactory.repo.RepoPathFactory
def getDirectorySizeRecursively(def repoPath){
def children = repositories.getChildren(repoPath)
if (children.size() == 0) return 0
def total = 0
children.each { item ->
if (item.folder) {
total += getDirectorySizeRecursively(item.repoPath)
} else {
total += item.size
}
}
total
}
executions {
/**
* This method expects parameter repoName to be passed. It will than calculate the TOTAL size of repository and return the value.
* If the repo name is invalid or not provided it will fail.
* Sample invokation:
* http://localhost:8081/artifactory/api/plugins/execute/getRepositorySize?params=repoName=ext-release-local
*/
getRepositorySize() { params ->
if (params.size() > 0 && params['repoName'] && params['repoName'].size() > 0){
def repoName = params['repoName'][0]
if (repositories.localRepositories.contains(repoName)){
message = getDirectorySizeRecursively(RepoPathFactory.create(repoName, '/'))
status = 200
} else {
message = "Repository $repoName doesn't exists"
status = 404
}
} else {
message = 'Missing repository name parameter repoName={name}'
status = 400
}
}
/**
* Prepare report on all repositories
* Sample invokation:
* http://localhost:8081/artifactory/api/plugins/execute/getAllRepositorySizes
*/
getAllRepositorySizes() { params ->
def repositoryReport = "[\n"
def totalNumberOfRepositories = repositories.localRepositories.size()
repositories.localRepositories.eachWithIndex { repoName, index ->
def repoPath = RepoPathFactory.create(repoName, '/')
def size = getDirectorySizeRecursively(repoPath)
repositoryReport+="{\"repoName\":\"$repoName\", \"sizeInBytes\": $size}"
if (index < totalNumberOfRepositories -1) {
repositoryReport+=",\n"
}
}
repositoryReport+="\n]"
message = repositoryReport
status = 200
}
}

[
{"repoName":"libs-release-local", "sizeInBytes": 122233},
{"repoName":"libs-snapshot-local", "sizeInBytes": 0},
{"repoName":"plugins-release-local", "sizeInBytes": 0},
{"repoName":"plugins-snapshot-local", "sizeInBytes": 0},
{"repoName":"ext-release-local", "sizeInBytes": 122233},
{"repoName":"ext-snapshot-local", "sizeInBytes": 0}
]

view raw
sample-response.json
hosted with ❤ by GitHub

To install plugin just copy the RepositorySize.groovy file to ARTIFACTORY_HOME/etc/plugins folder.

 

Groovy Map to Json String converter

I use Groovy a lot. It’s simple and easy to use, runs on JVM and saves me from Java verbosity. I also like the fact that it’s dynamic.

I use it with a simple Servlet to return data to JavaScript AJAX requests. I like to keep the server side very simple, so I don’t create a lot of POJOs and I’m using HashMaps instead. Groovy has few convenient methods that makes it easy to work with Maps.

I do convert the maps into JSON when returning results to a browser. I don’t use anything fancy, just a couple lines of Groovy code to do that.

class JsonMap {
def toJSON(elements, depth = 0) {
def json = ""
depth.times { json += "\t" }
json += "{"
elements.each { key, value ->
json += "\"$key\":"
json += jsonValue(value, depth)
json += ", "
}
json = (elements.size() > 0) ? json.substring(0, json.length() - 2) : json
json += "}"
json
}
private def jsonValue(element, depth) {
if (element instanceof Map) {
return "\n" + toJSON(element, depth + 1)
}
if (element instanceof List) {
def list = "["
element.each { elementFromList ->
list += jsonValue(elementFromList, depth)
list += ", "
}
list = (element.size() > 0) ? list.substring(0, list.length() - 2) : list
list += "]"
return list
}
(element instanceof String) ? "\"$element\"": element?.toString()
}
}
view raw JsonMap.groovy hosted with ❤ by GitHub
class MapToJsonTests extends GroovyTestCase {
private final def mapper = new JsonMap()
void test_convertMapWithListsOfMapsIntoJSON() {
def map = ["a": "a", "b": [["b": "a"], 'd', [12, 12, "e"], ["r": 12]]]
def expected = '''{"a":"a", "b":[
\t{"b":"a"}, "d", ["12", "12", "e"],
\t{"r":"12"}]}'''
def result = mapper.toJSON(map)
assert expected == result
}
}
view raw JsonMapTests.groovy hosted with ❤ by GitHub

With this code there is quite a bit of assumptions though:

  • it will only work for Map
  • it assumes Strings are used as Map Keys
  • it will convert Maps, Lists and Objects
  • when it meets Object it will call .toString() on it to get it’s value
  • it will try to format it with tabs and new lines a bit, so it’s more pleasant for the eye and human readable

Hope it would be useful for you. Greg