-
Notifications
You must be signed in to change notification settings - Fork 1
/
storagePlugin.groovy
241 lines (191 loc) · 8.72 KB
/
storagePlugin.groovy
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
/*
* Artifactory plugin for creating Altlinux repository
*/
import java.nio.file.Files
import org.artifactory.repo.RepoPath
import org.artifactory.repo.Repositories
import org.artifactory.repo.RepoPathFactory
import java.util.concurrent.locks.ReentrantLock
import org.artifactory.exception.CancelException
def ReentrantLock lock = new ReentrantLock();
def File filestoreDir = new File(ctx.artifactoryHome.dataDir, 'filestore')
storage {
// Return 409 if file is already exists in repository.
// genpkglist do not process duplicates, so it can't be used for editing, removing or quering
// so this check is needed to be sure that there is only one record for one file in it
beforeCreate { item ->
if (item.repoPath.path.contains("altlinux")) {
if (item.repoPath.isFile() && item.repoPath.path.endsWith(".rpm")) {
if (item.sha1 != null) {
throw new CancelException("Package with the name " + item.name + " already exists" ,409);
}
}
}
}
// before delete file check if it is enough free disk space to copy whole repo to it
// Removing will be denied if three disk space after copying all packages is lower than 5%
beforeDelete { item ->
if (item.repoPath.path.contains("altlinux")) {
if (item.repoPath.isFile() && item.repoPath.path.endsWith(".rpm")) {
def File packageFile = new File (item.repoPath.toString())
def File rpmsDir = packageFile.getParentFile()
def File rootDir = rpmsDir.getParentFile()
def File rpmsDirInRepo = new File (item.repoPath.path).getParentFile()
def RepoPath srcRepoPath = RepoPathFactory.create(item.repoPath.repoKey, rpmsDirInRepo.toString())
def srcItemInfo = repositories.getItemInfo(srcRepoPath)
if ( ! isFreeSpaceEnough(rootDir, srcRepoPath)) {
throw new CancelException("Not enough free space [" + item.repoPath + "] ", 500)
}
}
}
}
// Copy whole repo to local filesystem without deleted package and regenerate metadata
afterDelete { item ->
// Remove local filesystem directory associated with repository if it was deleted
if ( ! item.repoPath.isRoot()){
if (item.repoPath.getParent().isRoot()){
def File repoDir = new File (item.repoPath.toString())
repoDir.deleteDir()
log.warn("Directory " + repoDir + " associated with repository " + item.repoPath.repoKey + " successfully removed.")
}
}
if (item.repoPath.path.contains("altlinux")) {
if (item.repoPath.isFile() && item.repoPath.path.endsWith(".rpm")) {
def File packageFile = new File (item.repoPath.toString())
def File rpmsDir = packageFile.getParentFile()
def File rootDir = rpmsDir.getParentFile()
def File baseDir = new File (rootDir, 'base')
def String repoName = rpmsDir.getName().replaceAll('RPMS.', '')
def File rpmsDirInRepo = new File (item.repoPath.path).getParentFile()
def File rootDirInRepo = rpmsDirInRepo.getParentFile()
def File baseDirInRepo = new File(rootDirInRepo, 'base')
lock.lock()
try {
def RepoPath srcRepoPath = RepoPathFactory.create(item.repoPath.repoKey, rpmsDirInRepo.toString())
def srcItemInfo = repositories.getItemInfo(srcRepoPath)
// Copy repositories RPMS directory to local filesystem
def artifactsCount = repositories.getChildren(srcItemInfo.repoPath).size()
// Check if current artifact is the last
if (artifactsCount > 1) {
repositories.getChildren(srcItemInfo.repoPath).each {
if (it.repoPath != item.repoPath) {
def Thread thread = new Thread(){
public void run() {
def File packageDirInFilestore = new File(filestoreDir, it.sha1.substring(0, 2))
def File packageFileInFilestore = new File(packageDirInFilestore, it.sha1)
install(packageFileInFilestore.toString(), it.repoPath.toString())
}
}
thread.start()
}
}
log.warn("Recalculating of Rpm metadata started for " + item.repoPath.repoKey + ':' + rootDirInRepo)
genmetadata(rootDir.getAbsolutePath(), repoName, true)
}
// Deploy all generated files to artifactory
baseDir.eachFile {
def InputStream fileAsInputStream = new File (it.getAbsolutePath()).newInputStream()
def File fileRepoPath = new File (baseDirInRepo, it.getName())
if (artifactsCount > 1) {
if( ! deployRepoMetadata(item.repoPath.repoKey, fileRepoPath, fileAsInputStream)) {
throw new Exception ("Can't deploy " + fileRepoPath + " for package " + item.name)
}
} else {
// Remove all files in case of all artifacts deleting.
it.delete()
}
}
} catch(Exception e) {
throw new CancelException("ERROR: [" + item.name + "] " + e ,500);
} finally {
// Remove RPMS directory
rpmsDir.deleteDir()
lock.unlock()
}
}
}
}
afterCreate { item ->
if (item.repoPath.path.contains("altlinux")) {
if (item.repoPath.isFile() && item.repoPath.path.endsWith(".rpm")) {
def String sha1 = item.sha1
// Artifactory filestore path where file could be found as file on disk
// For example: /var/opt/jfrog/artifactory/data/artifactory/filestore/03/03b3124fe5d38900d2cc78cf3a3f7f367e38f75e
def File packageDirInFilestore = new File(filestoreDir, sha1.substring(0, 2))
def File packageFileInFilestore = new File(packageDirInFilestore, sha1)
// Path to save packages for packagelist generating on the filesystem
def File packageFile = new File (item.repoPath.toString())
def File rpmsDir = packageFile.getParentFile()
def File rootDir = rpmsDir.getParentFile()
def File baseDir = new File (rootDir, 'base')
def String repoName = rpmsDir.getName().replaceAll('RPMS.', '')
// Path to the pkglist in the repository (not on the filesystem)
def File rootDirInRepo = new File (item.repoPath.path).getParentFile().getParentFile()
def File baseDirInRepo = new File(rootDirInRepo, 'base')
lock.lock()
try {
// Create base directory
baseDir.mkdirs()
// Install package file from filestore to the directory wich will be used as dir for genpkglist
install(packageFileInFilestore.toString(), packageFile.toString())
log.info("Starting to calculate Rpm metadata for " + item.repoPath.repoKey + ':' + rootDirInRepo)
genmetadata(rootDir.getAbsolutePath(), repoName, false)
// Deploy all generated files to artifactory
baseDir.eachFile {
def InputStream fileAsInputStream = new File (it.getAbsolutePath()).newInputStream()
def File fileRepoPath = new File (baseDirInRepo, it.getName())
if(!deployRepoMetadata(item.repoPath.repoKey, fileRepoPath, fileAsInputStream)) {
throw new Exception ("Can't deploy " + fileRepoPath + " for package " + item.name)
}
}
} catch(Exception e) {
throw new CancelException("ERROR: [" + item.name + "] " + e ,500);
} finally {
// Remove rpm package
packageFile.delete()
lock.unlock()
}
}
}
}
}
def install (String sourceFile, String destinationFile) {
def installCmd = ExecuteConstants.installCommand.replace('{source}', sourceFile)
installCmd = installCmd.replace('{destination}', destinationFile)
execLn = installCmd.execute()
if (execLn.waitFor() != 0) {
throw new Exception("Non zero status returned: " + installCmd);
}
}
def genmetadata (String packageDir, String repositoryName, Boolean regenerate) {
def genmetadataCmd = ExecuteConstants.genmetadataCommand.replace('{pkgDir}', packageDir)
genmetadataCmd = genmetadataCmd.replace('{repoName}', repositoryName)
if(regenerate) {
genmetadataCmd = genmetadataCmd.replace('{options}','')
} else {
genmetadataCmd = genmetadataCmd.replace('{options}', '--append')
}
execLn = genmetadataCmd.execute()
if (execLn.waitFor() != 0) {
throw new Exception("Non zero status returned: " + genmetadataCmd);
}
}
def boolean isFreeSpaceEnough(File repoRoot, RepoPath srcRepoPath) {
def artifactsSize = repositories.getArtifactsSize(srcRepoPath)
def freePercent = Math.ceil((repoRoot.getFreeSpace() - artifactsSize) * 100 / repoRoot.getTotalSpace())
if ( freePercent < 5 ) {
return false
} else {
return true
}
}
def boolean deployRepoMetadata(String repoKey, File deployPath, InputStream binary) {
def String targetRepoKey = repoKey
def String targetPath = deployPath
def RepoPath deployRepoPath = RepoPathFactory.create(targetRepoKey, targetPath)
repositories.deploy(deployRepoPath, binary)
}
class ExecuteConstants {
static String installCommand = 'install -D {source} {destination}'
static String genmetadataCommand = '/var/opt/jfrog/artifactory/custom/bin/genmetadata {options} --topdir {pkgDir} --comp {repoName}'
}