1 package org.onap.sdc.dcae.catalog.asdc;
4 import java.net.URISyntaxException;
7 import java.io.IOException;
8 import java.io.UncheckedIOException;
10 import java.util.List;
12 import java.util.UUID;
13 import java.util.Collections;
15 import java.util.function.UnaryOperator;
17 import javax.annotation.PostConstruct;
19 import org.onap.sdc.common.onaplog.OnapLoggerDebug;
20 import org.onap.sdc.common.onaplog.OnapLoggerError;
21 import org.onap.sdc.common.onaplog.Enums.LogLevel;
22 import org.onap.sdc.dcae.enums.ArtifactGroupType;
23 import org.onap.sdc.dcae.enums.ArtifactType;
24 import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed;
25 import org.springframework.http.MediaType;
26 import org.springframework.http.HttpHeaders;
27 import org.springframework.http.HttpRequest;
28 import org.springframework.http.HttpMethod;
29 import org.springframework.http.HttpEntity;
30 import org.springframework.http.RequestEntity;
31 import org.springframework.http.ResponseEntity;
32 import org.springframework.http.client.AsyncClientHttpRequestExecution;
33 import org.springframework.http.client.AsyncClientHttpRequestInterceptor;
34 import org.springframework.http.client.ClientHttpResponse;
35 import org.springframework.web.client.AsyncRestTemplate;
36 import org.springframework.web.client.RestClientException;
37 import org.springframework.web.client.HttpClientErrorException;
38 import org.springframework.http.converter.HttpMessageConverter;
40 import org.springframework.util.Base64Utils;
41 //import org.springframework.util.DigestUtils;
42 import org.apache.commons.codec.digest.DigestUtils;
44 import org.springframework.stereotype.Component;
45 import org.springframework.context.annotation.Scope;
46 import org.springframework.scheduling.annotation.Scheduled;
47 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.util.concurrent.ListenableFuture;
50 import org.springframework.util.concurrent.ListenableFutureCallback;
52 import org.apache.commons.io.FileUtils;
53 import org.apache.commons.lang3.StringUtils;
55 import org.json.JSONObject;
56 import org.onap.sdc.dcae.catalog.commons.Action;
57 import org.onap.sdc.dcae.catalog.commons.Future;
58 import org.onap.sdc.dcae.catalog.commons.Futures;
59 import org.onap.sdc.dcae.catalog.commons.JSONHttpMessageConverter;
60 import org.onap.sdc.dcae.composition.util.DcaeBeConstants;
61 import org.onap.sdc.dcae.composition.util.SystemProperties;
62 import org.json.JSONArray;
64 import org.apache.commons.cli.BasicParser;
65 import org.apache.commons.cli.CommandLine;
66 import org.apache.commons.cli.CommandLineParser;
67 import org.apache.commons.cli.HelpFormatter;
68 import org.apache.commons.cli.OptionBuilder;
69 import org.apache.commons.cli.Options;
70 import org.apache.commons.cli.ParseException;
75 //@ConfigurationProperties(prefix="asdc")
78 public static enum AssetType {
84 // public static enum ArtifactType {
90 // DCAE_INVENTORY_TOSCA,
91 // DCAE_INVENTORY_JSON,
92 // DCAE_INVENTORY_POLICY,
93 // DCAE_INVENTORY_DOC,
94 // DCAE_INVENTORY_BLUEPRINT,
95 // DCAE_INVENTORY_EVENT,
105 // public static enum ArtifactGroupType {
110 public static enum LifecycleState {
118 // @Retention(RetentionPolicy.RUNTIME)
119 // @Target(ElementType.METHOD)
120 // public @interface Mandatory {
123 protected static OnapLoggerError errLogger = OnapLoggerError.getInstance();
124 protected static OnapLoggerDebug debugLogger = OnapLoggerDebug.getInstance();
127 private SystemProperties systemProperties;
130 private String rootPath = "/sdc/v1/catalog/";
133 private String instanceId;
136 public void setUri(URI theUri) {
137 //theUri = URI.create(systemProperties.getProperties().getProperty(SystemProperties.ASDC_CATALOG_URL));
138 String userInfo = theUri.getUserInfo();
139 if (userInfo != null) {
140 String[] userInfoParts = userInfo.split(":");
141 setUser(userInfoParts[0]);
142 if (userInfoParts.length > 1)
143 setPassword(userInfoParts[1]);
145 String fragment = theUri.getFragment();
146 if (fragment == null)
147 throw new IllegalArgumentException("The URI must contain a fragment specification, to be used as ASDC instance id");
148 setInstanceId(fragment);
151 this.rootUri = new URI(theUri.getScheme(), null, theUri.getHost(), theUri.getPort(), theUri.getPath(), theUri.getQuery(), null);
153 catch (URISyntaxException urix) {
154 throw new IllegalArgumentException("Invalid uri", urix);
158 public URI getUri() {
162 public void setUser(String theUser) {
166 public String getUser() {
170 public void setPassword(String thePassword) {
171 this.passwd = thePassword;
174 public String getPassword() {
178 public void setInstanceId(String theId) {
179 this.instanceId = theId;
182 public String getInstanceId() {
183 return this.instanceId;
186 public void setRootPath(String thePath) {
187 this.rootPath = systemProperties.getProperties().getProperty(DcaeBeConstants.Config.ASDC_ROOTPATH);
190 public String getRootPath() {
191 return systemProperties.getProperties().getProperty(DcaeBeConstants.Config.ASDC_ROOTPATH);
194 @Scheduled(fixedRateString = "${beans.context.scripts.updateCheckFrequency?:60000}")
195 public void checkForUpdates() {
199 public void initASDC() {
202 public <T> Future<T> getResources(Class<T> theType) {
203 return getAssets(AssetType.resource, theType);
206 public Future<JSONArray> getResources() {
207 return getAssets(AssetType.resource, JSONArray.class);
210 public <T> Future<T> getResources(Class<T> theType, String theCategory, String theSubCategory) {
211 return getAssets(AssetType.resource, theType, theCategory, theSubCategory);
214 public Future<JSONArray> getResources(String category, String subCategory, String resourceType) {
215 return getAssets(AssetType.resource, JSONArray.class, category, subCategory, resourceType);
218 public <T> Future<T> getServices(Class<T> theType) {
219 return getAssets(AssetType.service, theType);
222 public Future<JSONArray> getServices() {
223 return getAssets(AssetType.service, JSONArray.class);
226 public <T> Future<T> getServices(Class<T> theType, String theCategory, String theSubCategory) {
227 return getAssets(AssetType.service, theType, theCategory, theSubCategory);
230 public Future<JSONArray> getServices(String theCategory, String theSubCategory) {
231 return getAssets(AssetType.service, JSONArray.class, theCategory, theSubCategory);
234 public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType) {
235 return fetch(refAssets(theAssetType), theType);
238 public <T> Action<T> getAssetsAction(AssetType theAssetType, Class<T> theType) {
239 return (() -> fetch(refAssets(theAssetType), theType));
242 public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType,
243 String theCategory, String theSubCategory) {
244 return getAssets(theAssetType, theType, theCategory, theSubCategory, null);
247 public <T> Future<T> getAssets(AssetType theAssetType, Class<T> theType,
248 String theCategory, String theSubCategory, String theResourceType) {
249 return fetch(refAssets(theAssetType) + filter(theCategory, theSubCategory, theResourceType), theType);
252 public <T> Action<T> getAssetsAction(AssetType theAssetType, Class<T> theType,
253 String theCategory, String theSubCategory, String theResourceType) {
254 return (() -> fetch(refAssets(theAssetType) + filter(theCategory, theSubCategory, theResourceType), theType));
257 protected String refAssets(AssetType theAssetType) {
258 return this.rootPath + theAssetType + "s/";
261 private String filter(String theCategory, String theSubCategory, String theResourceType) {
262 StringBuilder filter = null;
263 if (theCategory != null) {
264 filter = new StringBuilder();
265 filter.append("?category=")
266 .append(theCategory);
267 if (theSubCategory != null) {
268 filter.append("&subCategory=")
269 .append(theSubCategory);
270 if (theResourceType != null) {
271 filter.append("&resourceType=")
272 .append(theResourceType);
276 return filter == null ? "" : filter.toString();
279 protected String refAsset(AssetType theAssetType, UUID theId) {
280 return this.rootPath + theAssetType + "s/" + theId;
283 public <T> Future<T> getResource(UUID theId, Class<T> theType) {
284 return getAsset(AssetType.resource, theId, theType);
287 public Future<JSONObject> getResource(UUID theId) {
288 return getAsset(AssetType.resource, theId, JSONObject.class);
291 public Future<ResourceDetailed> getSDCResource(UUID theId) {
292 return getAsset(AssetType.resource, theId, ResourceDetailed.class);
296 public <T> Future<T> getService(UUID theId, Class<T> theType) {
297 return getAsset(AssetType.service, theId, theType);
300 public Future<JSONObject> getService(UUID theId) {
301 return getAsset(AssetType.service, theId, JSONObject.class);
304 public <T> Future<T> getAsset(AssetType theAssetType, UUID theId, Class<T> theType) {
305 return fetch(refAsset(theAssetType, theId) + "/metadata", theType);
308 public <T> Action<T> getAssetAction(AssetType theAssetType, UUID theId, Class<T> theType) {
309 return (() -> fetch(refAsset(theAssetType, theId) + "/metadata", theType));
312 public Future<byte[]> getResourceArchive(UUID theId) {
313 return getAssetArchive(AssetType.resource, theId);
316 public Future<byte[]> getServiceArchive(UUID theId) {
317 return getAssetArchive(AssetType.service, theId);
320 public Future<byte[]> getAssetArchive(AssetType theAssetType, UUID theId) {
321 return fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class);
324 public Action<byte[]> getAssetArchiveAction(AssetType theAssetType, UUID theId) {
325 return (() -> fetch(refAsset(theAssetType, theId) + "/toscaModel", byte[].class));
328 public Future<JSONObject> checkinResource(UUID theId, String theUser, String theMessage) {
329 return cycleAsset(AssetType.resource, theId, LifecycleState.Checkin, theUser, theMessage);
332 public Future<JSONObject> checkinService(UUID theId, String theUser, String theMessage) {
333 return cycleAsset(AssetType.service, theId, LifecycleState.Checkin, theUser, theMessage);
336 public Future<JSONObject> checkoutResource(UUID theId, String theUser, String theMessage) {
337 return cycleAsset(AssetType.resource, theId, LifecycleState.Checkout, theUser, theMessage);
340 public Future<JSONObject> checkoutService(UUID theId, String theUser, String theMessage) {
341 return cycleAsset(AssetType.service, theId, LifecycleState.Checkout, theUser, theMessage);
344 public Future<JSONObject> certifyResource(UUID theId, String theUser, String theMessage) {
345 return cycleAsset(AssetType.resource, theId, LifecycleState.Certify, theUser, theMessage);
348 public Future<JSONObject> certifyService(UUID theId, String theUser, String theMessage) {
349 return cycleAsset(AssetType.service, theId, LifecycleState.Certify, theUser, theMessage);
352 /* Normally theMessage is mandatory (and we'd use put instead of putOpt) but .. not so for undocheckout ..
354 public Future<JSONObject> cycleAsset(AssetType theAssetType, UUID theId, LifecycleState theState,
355 String theUser, String theMessage) {
356 return post(refAsset(theAssetType, theId) + "/lifecycleState/" + theState,
357 (headers) -> prepareHeaders(headers)
358 .header("USER_ID", theUser),
359 new JSONObject().putOpt("userRemarks", theMessage));
362 protected String refAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theAssetInstance, UUID theArtifactId) {
363 return refAsset(theAssetType, theAssetId) + "/resourceInstances/" + theAssetInstance + "/artifacts" + (theArtifactId == null ? "" : ("/" + theArtifactId));
366 protected String refAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId) {
367 return refAsset(theAssetType, theAssetId) + "/artifacts" + (theArtifactId == null ? "" : ("/" + theArtifactId));
370 public <T> Future<T> getResourceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
371 return getAssetArtifact(AssetType.resource, theAssetId, theArtifactId, theType);
374 public <T> Future<T> getServiceArtifact(UUID theAssetId, UUID theArtifactId, Class<T> theType) {
375 return getAssetArtifact(AssetType.service, theAssetId, theArtifactId, theType);
378 public <T> Future<T> getResourceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance, Class<T> theType) {
379 return getAssetInstanceArtifact(AssetType.resource, theAssetId, theInstance, theArtifactId, theType);
382 public <T> Future<T> getServiceInstanceArtifact(UUID theAssetId, UUID theArtifactId, String theInstance, Class<T> theType) {
383 return getAssetInstanceArtifact(AssetType.service, theAssetId, theInstance, theArtifactId, theType);
386 public <T> Future<T> getAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId, Class<T> theType) {
387 return fetch(refAssetArtifact(theAssetType, theAssetId, theArtifactId), theType);
390 public <T> Action<T> getAssetArtifactAction(AssetType theAssetType, UUID theAssetId, UUID theArtifactId, Class<T> theType) {
391 return (() -> fetch(refAssetArtifact(theAssetType, theAssetId, theArtifactId), theType));
394 public <T> Future<T> getAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance, UUID theArtifactId, Class<T> theType) {
395 return fetch(refAssetInstanceArtifact(theAssetType, theAssetId, theInstance, theArtifactId), theType);
398 public <T> Action<T> getAssetInstanceArtifactAction(AssetType theAssetType, UUID theAssetId, String theInstance, UUID theArtifactId, Class<T> theType) {
399 return (() -> fetch(refAssetInstanceArtifact(theAssetType, theAssetId, theInstance, theArtifactId), theType));
402 public ArtifactUploadAction createResourceArtifact(UUID theAssetId) {
403 return createAssetArtifact(AssetType.resource, theAssetId);
406 public ArtifactUploadAction createServiceArtifact(UUID theAssetId) {
407 return createAssetArtifact(AssetType.service, theAssetId);
410 public ArtifactUploadAction createResourceInstanceArtifact(UUID theAssetId, String theInstance) {
411 return createAssetInstanceArtifact(AssetType.resource, theAssetId, theInstance);
414 public ArtifactUploadAction createServiceInstanceArtifact(UUID theAssetId, String theInstance) {
415 return createAssetInstanceArtifact(AssetType.service, theAssetId, theInstance);
418 public ArtifactUploadAction createAssetArtifact(AssetType theAssetType, UUID theAssetId) {
419 return new ArtifactUploadAction()
420 .ofAsset(theAssetType, theAssetId);
423 public ArtifactUploadAction createAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance) {
424 return new ArtifactUploadAction()
425 .ofAssetInstance(theAssetType, theAssetId, theInstance);
428 public ArtifactUpdateAction updateResourceArtifact(UUID theAssetId, JSONObject theArtifactInfo) {
429 return updateAssetArtifact(AssetType.resource, theAssetId, theArtifactInfo);
432 public ArtifactUpdateAction updateResourceInstanceArtifact(UUID theAssetId, String theInstance, JSONObject theArtifactInfo) {
433 return updateAssetInstanceArtifact(AssetType.resource, theAssetId, theInstance, theArtifactInfo);
436 public ArtifactUpdateAction updateServiceArtifact(UUID theAssetId, JSONObject theArtifactInfo) {
437 return updateAssetArtifact(AssetType.service, theAssetId, theArtifactInfo);
440 public ArtifactUpdateAction updateServiceInstanceArtifact(UUID theAssetId, String theInstance, JSONObject theArtifactInfo) {
441 return updateAssetInstanceArtifact(AssetType.service, theAssetId, theInstance, theArtifactInfo);
444 public ArtifactUpdateAction updateAssetArtifact(AssetType theAssetType, UUID theAssetId, JSONObject theArtifactInfo) {
445 return new ArtifactUpdateAction(theArtifactInfo)
446 .ofAsset(theAssetType, theAssetId);
449 public ArtifactUpdateAction updateAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance, JSONObject theArtifactInfo) {
450 return new ArtifactUpdateAction(theArtifactInfo)
451 .ofAssetInstance(theAssetType, theAssetId, theInstance);
454 public ArtifactDeleteAction deleteResourceArtifact(UUID theAssetId, UUID theArtifactId) {
455 return deleteAssetArtifact(AssetType.resource, theAssetId, theArtifactId);
458 public ArtifactDeleteAction deleteResourceInstanceArtifact(UUID theAssetId, String theInstance, UUID theArtifactId) {
459 return deleteAssetInstanceArtifact(AssetType.resource, theAssetId, theInstance, theArtifactId);
462 public ArtifactDeleteAction deleteServiceArtifact(UUID theAssetId, UUID theArtifactId) {
463 return deleteAssetArtifact(AssetType.service, theAssetId, theArtifactId);
466 public ArtifactDeleteAction deleteServiceInstanceArtifact(UUID theAssetId, String theInstance, UUID theArtifactId) {
467 return deleteAssetInstanceArtifact(AssetType.service, theAssetId, theInstance, theArtifactId);
470 public ArtifactDeleteAction deleteAssetArtifact(AssetType theAssetType, UUID theAssetId, UUID theArtifactId) {
471 return new ArtifactDeleteAction(theArtifactId)
472 .ofAsset(theAssetType, theAssetId);
475 public ArtifactDeleteAction deleteAssetInstanceArtifact(AssetType theAssetType, UUID theAssetId, String theInstance, UUID theArtifactId) {
476 return new ArtifactDeleteAction(theArtifactId)
477 .ofAssetInstance(theAssetType, theAssetId, theInstance);
481 public abstract class ASDCAction<A extends ASDCAction<A, T>, T> implements Action<T> {
483 protected JSONObject info; //info passed to asdc as request body
484 protected String operatorId; //id of the SDC user performing the action
486 protected ASDCAction(JSONObject theInfo) {
490 protected abstract A self();
492 protected ASDC asdc() {
496 protected A withInfo(JSONObject theInfo) {
497 merge(this.info, theInfo);
501 public A with(String theProperty, Object theValue) {
502 info.put(theProperty, theValue);
506 public A withOperator(String theOperator) {
507 this.operatorId = theOperator;
511 protected abstract String[] mandatoryInfoEntries();
513 protected void checkOperatorId() {
514 if (this.operatorId == null) {
515 throw new IllegalStateException("No operator id was provided");
519 protected void checkMandatoryInfo() {
520 for (String field: mandatoryInfoEntries()) {
521 if (!info.has(field))
522 throw new IllegalStateException("No '" + field + "' was provided");
526 protected void checkMandatory() {
528 checkMandatoryInfo();
532 protected static final String[] artifactMandatoryEntries = new String[] {};
535 * We use teh same API to operate on artifacts attached to assets or to their instances
537 public abstract class ASDCArtifactAction<A extends ASDCArtifactAction<A>> extends ASDCAction<A, JSONObject> {
539 protected AssetType assetType;
540 protected UUID assetId;
541 protected String assetInstance;
543 protected ASDCArtifactAction(JSONObject theInfo) {
547 protected A ofAsset(AssetType theAssetType, UUID theAssetId) {
548 this.assetType = theAssetType;
549 this.assetId = theAssetId;
553 protected A ofAssetInstance(AssetType theAssetType, UUID theAssetId, String theInstance) {
554 this.assetType = theAssetType;
555 this.assetId = theAssetId;
556 this.assetInstance = theInstance;
560 protected String normalizeInstanceName(String theName) {
561 return StringUtils.removePattern(theName, "[ \\.\\-]+").toLowerCase();
564 protected String[] mandatoryInfoEntries() {
565 return ASDC.this.artifactMandatoryEntries;
568 protected String ref(UUID theArtifactId) {
569 return (this.assetInstance == null) ?
570 refAssetArtifact(this.assetType, this.assetId, theArtifactId) :
571 refAssetInstanceArtifact(this.assetType, this.assetId, normalizeInstanceName(this.assetInstance), theArtifactId);
575 protected static final String[] uploadMandatoryEntries = new String[] { "artifactName",
582 public class ArtifactUploadAction extends ASDCArtifactAction<ArtifactUploadAction> {
584 protected ArtifactUploadAction() {
585 super(new JSONObject());
588 protected ArtifactUploadAction self() {
592 public ArtifactUploadAction withContent(byte[] theContent) {
593 return with("payloadData", Base64Utils.encodeToString(theContent));
596 public ArtifactUploadAction withContent(File theFile) throws IOException {
597 return withContent(FileUtils.readFileToByteArray(theFile));
600 public ArtifactUploadAction withLabel(String theLabel) {
601 return with("artifactLabel", theLabel);
604 public ArtifactUploadAction withName(String theName) {
605 return with("artifactName", theName);
608 public ArtifactUploadAction withDisplayName(String theName) {
609 return with("artifactDisplayName", theName);
612 public ArtifactUploadAction withType(ArtifactType theType) {
613 return with("artifactType", theType.toString());
616 public ArtifactUploadAction withGroupType(ArtifactGroupType theGroupType) {
617 return with("artifactGroupType", theGroupType.toString());
620 public ArtifactUploadAction withDescription(String theDescription) {
621 return with("description", theDescription);
624 protected String[] mandatoryInfoEntries() {
625 return ASDC.this.uploadMandatoryEntries;
628 public Future<JSONObject> execute() {
630 return ASDC.this.post(ref(null),
631 (headers) -> prepareHeaders(headers)
632 .header("USER_ID", this.operatorId),
637 protected static final String[] updateMandatoryEntries = new String[] { "artifactName",
645 * In its current form the update relies on a previous artifact retrieval. One cannot build an update from scratch.
646 * The label, tye and group type must be submitted but cannot be updated
648 public class ArtifactUpdateAction extends ASDCArtifactAction<ArtifactUpdateAction> {
651 protected ArtifactUpdateAction(JSONObject theInfo) {
655 protected ArtifactUpdateAction self() {
659 public ArtifactUpdateAction withContent(byte[] theContent) {
660 return with("payloadData", Base64Utils.encodeToString(theContent));
663 public ArtifactUpdateAction withContent(File theFile) throws IOException {
664 return withContent(FileUtils.readFileToByteArray(theFile));
667 public ArtifactUpdateAction withDescription(String theDescription) {
668 return with("description", theDescription);
671 public ArtifactUpdateAction withName(String theName) {
672 return with("artifactName", theName);
675 protected String[] mandatoryInfoEntries() {
676 return ASDC.this.updateMandatoryEntries;
679 /* The json object originates (normally) from a get so it will have entries we need to cleanup */
680 protected void cleanupInfoEntries() {
681 this.info.remove("artifactChecksum");
682 this.info.remove("artifactUUID");
683 this.info.remove("artifactVersion");
684 this.info.remove("artifactURL");
685 this.info.remove("artifactDescription");
688 public Future<JSONObject> execute() {
689 UUID artifactUUID = UUID.fromString(this.info.getString("artifactUUID"));
691 cleanupInfoEntries();
692 return ASDC.this.post(ref(artifactUUID),
693 (headers) -> prepareHeaders(headers)
694 .header("USER_ID", this.operatorId),
699 public class ArtifactDeleteAction extends ASDCArtifactAction<ArtifactDeleteAction> {
701 private UUID artifactId;
703 protected ArtifactDeleteAction(UUID theArtifactId) {
705 this.artifactId = theArtifactId;
708 protected ArtifactDeleteAction self() {
712 public Future<JSONObject> execute() {
714 return ASDC.this.delete(ref(this.artifactId),
715 (headers) -> prepareHeaders(headers)
716 .header("USER_ID", this.operatorId));
723 public VFCMTCreateAction createVFCMT() {
724 return new VFCMTCreateAction();
727 protected static final String[] vfcmtMandatoryEntries = new String[] { "name",
733 public class VFCMTCreateAction extends ASDCAction<VFCMTCreateAction, JSONObject> {
735 protected VFCMTCreateAction() {
737 super(new JSONObject());
739 .with("resourceType", "VFCMT")
740 .with("category", "Template")
741 .with("subcategory", "Monitoring Template")
742 .with("icon", "defaulticon");
745 protected VFCMTCreateAction self() {
749 public VFCMTCreateAction withName(String theName) {
750 return with("name", theName);
753 public VFCMTCreateAction withDescription(String theDescription) {
754 return with("description", theDescription);
757 public VFCMTCreateAction withVendorName(String theVendorName) {
758 return with("vendorName", theVendorName);
761 public VFCMTCreateAction withVendorRelease(String theVendorRelease) {
762 return with("vendorRelease", theVendorRelease);
765 public VFCMTCreateAction withTags(String... theTags) {
766 for (String tag: theTags)
767 this.info.append("tags", tag);
771 public VFCMTCreateAction withIcon(String theIcon) {
772 return with("icon", theIcon);
775 protected String[] mandatoryInfoEntries() {
776 return ASDC.this.vfcmtMandatoryEntries;
779 public VFCMTCreateAction withContact(String theContact) {
780 return with("contactId", theContact);
783 public Future<JSONObject> execute() {
785 this.info.putOnce("contactId", this.operatorId);
786 this.info.append("tags", info.optString("name"));
788 return ASDC.this.post(refAssets(AssetType.resource),
789 (headers) -> prepareHeaders(headers)
790 .header("USER_ID", this.operatorId),
796 public static JSONObject merge(JSONObject theOriginal, JSONObject thePatch) {
797 for (String key: (Set<String>)thePatch.keySet()) {
798 if (!theOriginal.has(key))
799 theOriginal.put(key, thePatch.get(key));
804 protected URI refUri(String theRef) {
806 return new URI(this.rootUri + theRef);
808 catch(URISyntaxException urisx) {
809 throw new UncheckedIOException(new IOException(urisx));
813 private HttpHeaders prepareHeaders() {
814 HttpHeaders headers = new HttpHeaders();
815 headers.add(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((this.user + ":" + this.passwd).getBytes()));
816 headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
817 headers.add(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE);
818 headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE);
819 headers.add("X-ECOMP-InstanceID", this.instanceId);
824 private RequestEntity.HeadersBuilder prepareHeaders(RequestEntity.HeadersBuilder theBuilder) {
826 .header(HttpHeaders.AUTHORIZATION, "Basic " + Base64Utils.encodeToString((this.user + ":" + this.passwd).getBytes()))
827 .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
828 .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_OCTET_STREAM_VALUE)
829 .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_UTF8_VALUE)
830 .header("X-ECOMP-InstanceID", this.instanceId);
833 public <T> Future<T> fetch(String theRef, Class<T> theContentType) {
834 return exchange(theRef, HttpMethod.GET, new HttpEntity(prepareHeaders()), theContentType);
837 public Future<JSONObject> post(String theRef, JSONObject thePost) {
838 return exchange(theRef, HttpMethod.POST, new HttpEntity<JSONObject>(thePost, prepareHeaders()), JSONObject.class);
841 public Future<JSONObject> post(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder, JSONObject thePost) {
842 RequestEntity.BodyBuilder builder = RequestEntity.post(refUri(theRef));
843 theHeadersBuilder.apply(builder);
845 return exchange(theRef, HttpMethod.POST, builder.body(thePost), JSONObject.class);
848 public Future<JSONObject> delete(String theRef, UnaryOperator<RequestEntity.HeadersBuilder> theHeadersBuilder) {
850 RequestEntity.HeadersBuilder builder = RequestEntity.delete(refUri(theRef));
851 theHeadersBuilder.apply(builder);
853 return exchange(theRef, HttpMethod.DELETE, builder.build(), JSONObject.class);
856 public <T> Future<T> exchange(String theRef, HttpMethod theMethod, HttpEntity theRequest, Class<T> theResponseType) {
858 AsyncRestTemplate restTemplate = new AsyncRestTemplate();
860 List<HttpMessageConverter<?>> converters = restTemplate.getMessageConverters();
861 converters.add(0, new JSONHttpMessageConverter());
862 restTemplate.setMessageConverters(converters);
864 restTemplate.setInterceptors(Collections.singletonList(new ContentMD5Interceptor()));
865 ASDCFuture<T> result = new ASDCFuture<T>();
866 String uri = this.rootUri + theRef;
869 .exchange(uri, theMethod, theRequest, theResponseType)
870 .addCallback(result.callback);
872 catch (RestClientException rcx) {
873 errLogger.log(LogLevel.WARN, this.getClass().getName(), "Failed to fetch {} {}", uri, rcx);
874 return Futures.failedFuture(rcx);
876 catch (Exception x) {
877 errLogger.log(LogLevel.WARN, this.getClass().getName(), "Failed to fetch {} {}", uri, x);
878 return Futures.failedFuture(x);
886 public class ASDCFuture<T>
887 extends Futures.BasicFuture<T> {
889 private boolean http404toEmpty = false;
894 public ASDCFuture setHttp404ToEmpty(boolean doEmpty) {
895 this.http404toEmpty = doEmpty;
899 ListenableFutureCallback<ResponseEntity<T>> callback = new ListenableFutureCallback<ResponseEntity<T>>() {
901 public void onSuccess(ResponseEntity<T> theResult) {
902 ASDCFuture.this.result(theResult.getBody());
905 public void onFailure(Throwable theError) {
906 if (theError instanceof HttpClientErrorException) {
907 // if (theError.getRawStatusCode() == 404 && this.http404toEmpty)
908 // ASDCFuture.this.result(); //th eresult is of type T ...
910 ASDCFuture.this.cause(new ASDCException((HttpClientErrorException)theError));
913 ASDCFuture.this.cause(theError);
920 public class ContentMD5Interceptor implements AsyncClientHttpRequestInterceptor {
923 public ListenableFuture<ClientHttpResponse> intercept(
924 HttpRequest theRequest, byte[] theBody, AsyncClientHttpRequestExecution theExecution)
926 if (HttpMethod.POST == theRequest.getMethod()) {
927 HttpHeaders headers = theRequest.getHeaders();
928 headers.add("Content-MD5", Base64Utils.encodeToString(
929 //DigestUtils.md5Digest(theBody)));
930 DigestUtils.md5Hex(theBody).getBytes()));
933 return theExecution.executeAsync(theRequest, theBody);
937 public static void main(String[] theArgs) throws Exception {
939 CommandLineParser parser = new BasicParser();
941 String user_id = "jh0003";
943 Options options = new Options();
944 options.addOption(OptionBuilder
945 .withArgName("target")
946 .withLongOpt("target")
947 .withDescription("target asdc system")
952 options.addOption(OptionBuilder
953 .withArgName("action")
954 .withLongOpt("action")
955 .withDescription("one of: list, get, getartifact, checkin, checkout")
960 options.addOption(OptionBuilder
961 .withArgName("assetType")
962 .withLongOpt("assetType")
963 .withDescription("one of resource, service, product")
966 .create('k') ); //k for 'kind' ..
968 options.addOption(OptionBuilder
969 .withArgName("assetId")
970 .withLongOpt("assetId")
971 .withDescription("asset uuid")
973 .create('u') ); //u for 'uuid'
975 options.addOption(OptionBuilder
976 .withArgName("artifactId")
977 .withLongOpt("artifactId")
978 .withDescription("artifact uuid")
980 .create('s') ); //s for 'stuff'
982 options.addOption(OptionBuilder
983 .withArgName("listFilter")
984 .withLongOpt("listFilter")
985 .withDescription("filter for list operations")
987 .create('f') ); //u for 'uuid'
989 CommandLine line = null;
991 line = parser.parse(options, theArgs);
993 catch(ParseException exp) {
994 errLogger.log(LogLevel.ERROR, ASDC.class.getName(), exp.getMessage());
995 new HelpFormatter().printHelp("asdc", options);
999 ASDC asdc = new ASDC();
1000 asdc.setUri(new URI(line.getOptionValue("target")));
1002 String action = line.getOptionValue("action");
1003 if (action.equals("list")) {
1004 JSONObject filterInfo = new JSONObject(
1005 line.hasOption("listFilter") ?
1006 line.getOptionValue("listFilter") : "{}");
1008 asdc.getAssets(ASDC.AssetType.valueOf(line.getOptionValue("assetType")), JSONArray.class,
1009 filterInfo.optString("category", null), filterInfo.optString("subCategory", null))
1011 for (int i = 0; i < assets.length(); i++) {
1012 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),"> {}", assets.getJSONObject(i).toString(2));
1015 else if (action.equals("get")) {
1016 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),
1017 asdc.getAsset(ASDC.AssetType.valueOf(line.getOptionValue("assetType")),
1018 UUID.fromString(line.getOptionValue("assetId")),
1024 else if (action.equals("getartifact")) {
1025 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),
1026 asdc.getAssetArtifact(ASDC.AssetType.valueOf(line.getOptionValue("assetType")),
1027 UUID.fromString(line.getOptionValue("assetId")),
1028 UUID.fromString(line.getOptionValue("artifactId")),
1033 else if (action.equals("checkin")) {
1034 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),
1035 asdc.cycleAsset(ASDC.AssetType.valueOf(line.getOptionValue("assetType")),
1036 UUID.fromString(line.getOptionValue("assetId")),
1037 ASDC.LifecycleState.Checkin,
1044 else if (action.equals("checkout")) {
1045 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),
1046 asdc.cycleAsset(ASDC.AssetType.valueOf(line.getOptionValue("assetType")),
1047 UUID.fromString(line.getOptionValue("assetId")),
1048 ASDC.LifecycleState.Checkout,
1055 else if (action.equals("cleanup")) {
1056 JSONArray resources = asdc.getResources()
1058 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),"Got {} resources", resources.length());
1061 for (int i = 0; i < resources.length(); i++) {
1063 JSONObject resource = resources.getJSONObject(i);
1065 if (resource.getString("resourceType").equals("VFCMT") &&
1066 resource.getString("name").contains("test")) {
1068 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),"undocheckout for {}", resource.getString("uuid"));
1071 asdc.cycleAsset(AssetType.resource, UUID.fromString(resource.getString("uuid")), LifecycleState.undocheckout, user_id, null)
1074 catch (Exception x) {
1075 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),"** {}", x);
1083 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),
1085 .withName("Clonator")
1086 .withDescription("Clone operation target 06192017")
1087 .withVendorName("CloneInc")
1088 .withVendorRelease("1.0")
1090 .withOperator(user_id)
1096 catch(Exception x) {
1097 debugLogger.log(LogLevel.DEBUG, ASDC.class.getName(),"Failed to create VFCMT: {}", x);