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: Amazon S3 integration for assets and transfers #18

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
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
4 changes: 4 additions & 0 deletions src/modules/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ import {environment} from "../../environments/environment";
provide: 'STORAGE_TYPES',
useFactory: () => [{id: "AzureStorage", name: "AzureStorage"}, {id: "AmazonS3", name: "AmazonS3"}],
},
{
provide: 'AWS_REGIONS',
useFactory: () => ["us-east-1", "us-east-2", "us-west-1", "us-west-2", "ap-south-1", "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-west-3", "eu-north-1", "sa-east-1", "af-south-1", "ap-east-1", "ap-south-2", "ap-southeast-3", "eu-south-1", "eu-south-2", "eu-central-2", "me-south-1", "me-central-1"],
},
{
provide: Configuration,
useFactory: (s: AppConfigService) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,34 @@
<div>
<mat-form-field class="form-field" color="accent" id="form-field-destination">
<mat-label>Destination</mat-label>
<mat-select [(ngModel)]="storageTypeId" disabled>
<mat-select [(ngModel)]="storageTypeId" >
<mat-option *ngFor="let storageType of storageTypes " [value]="storageType.id">
{{storageType.name}}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field class="form-field" color="accent" id="form-field-account">
<mat-label>Account</mat-label>
<input [(ngModel)]="account" matInput>
<mat-label *ngIf="storageTypeId==='AmazonS3'">Region</mat-label>
<mat-label *ngIf="storageTypeId==='AzureStorage'">Account</mat-label>
<input [(ngModel)]="param1" matInput *ngIf="storageTypeId==='AzureStorage'">
<mat-select [(ngModel)]="param1" *ngIf="storageTypeId==='AmazonS3'">
<mat-option *ngFor="let awsRegion of awsRegions" [value]="awsRegion">
{{awsRegion}}
</mat-option>
</mat-select>
</mat-form-field>

<mat-form-field class="form-field" color="accent" id="form-field-container">
<mat-label>Container</mat-label>
<input disabled [(ngModel)]="container" matInput>
<mat-label *ngIf="storageTypeId==='AmazonS3'">Bucket Name</mat-label>
<mat-label *ngIf="storageTypeId==='AzureStorage'">Container Name</mat-label>
<input [(ngModel)]="param2" matInput>
</mat-form-field>

<mat-form-field class="form-field" color="accent" id="form-field-blobname">
<mat-label>Blob Name</mat-label>
<input [(ngModel)]="blobname" matInput>
<mat-label *ngIf="storageTypeId==='AmazonS3'">Key Name</mat-label>
<mat-label *ngIf="storageTypeId==='AzureStorage'">Blob Name</mat-label>
<input [(ngModel)]="param3" matInput>
</mat-form-field>
</div>
</mat-dialog-content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,38 +17,66 @@ export class AssetEditorDialog implements OnInit {
contenttype: string = '';

storageTypeId: string = 'AzureStorage';
account: string = '';
container: string = 'src-container';
blobname: string = '';
// Azure Account or AWS Region (dependent on selected storage type)
param1: string = '';

// Azure Container or AWS S3 Bucket (dependent on selected storage type)
param2: string = 'src-container';

//Azure Blob Name or AWS S3 Object Key (dependent on selected storage type)
param3: string = '';

constructor(private assetService: AssetService, private dialogRef: MatDialogRef<AssetEditorDialog>,
@Inject('STORAGE_TYPES') public storageTypes: StorageType[]) {
@Inject('AWS_REGIONS') public awsRegions: string[], @Inject('STORAGE_TYPES') public storageTypes: StorageType[]) {
}

ngOnInit(): void {
}

onSave() {
const assetEntryDto: AssetEntryDto = {
asset: {
properties: {
"asset:prop:name": this.name,
"asset:prop:version": this.version,
"asset:prop:id": this.id,
"asset:prop:contenttype": this.contenttype,
}
},
dataAddress: {
properties: {
"type": this.storageTypeId,
"account": this.account,
"container": this.container,
"blobname": this.blobname,
"keyName": `${this.account}-key1`
if(this.storageTypeId=='AzureStorage'){
const assetEntryDto: AssetEntryDto = {
asset: {
properties: {
"asset:prop:name": this.name,
"asset:prop:version": this.version,
"asset:prop:id": this.id,
"asset:prop:contenttype": this.contenttype,
}
},
}
};
dataAddress: {
properties: {
"type": this.storageTypeId,
"account": this.param1,
"container": this.param2,
"blobname": this.param3,
"keyName": `${this.param1}-key1`
},
}
};

this.dialogRef.close({ assetEntryDto });
this.dialogRef.close({ assetEntryDto });
}else if(this.storageTypeId=='AmazonS3'){
const assetEntryDto: AssetEntryDto = {
asset: {
properties: {
"asset:prop:name": this.name,
"asset:prop:version": this.version,
"asset:prop:id": this.id,
"asset:prop:contenttype": this.contenttype,
}
},
dataAddress: {
properties: {
"type": this.storageTypeId,
"region": this.param1,
"bucketName": this.param2,
"keyName": this.param3
},
}
};

this.dialogRef.close({ assetEntryDto });
}
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
<mat-dialog-content *ngIf="storageTypes as storageTypes">
<div>
<mat-form-field class="form-field" color="accent" id="form-field-destination">
<mat-label>Destination</mat-label>
<mat-select [(ngModel)]="storageTypeId">
<mat-option *ngFor="let storageType of storageTypes" [value]="storageType.id">
{{storageType.name}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<mat-form-field class="form-field" color="accent" id="form-field-destination">
<mat-label>Destination</mat-label>
<mat-select [(ngModel)]="storageTypeId">
<mat-option *ngFor="let storageType of storageTypes" [value]="storageType.id">
{{storageType.name}}
</mat-option>
</mat-select>
</mat-form-field>
<div>
<mat-form-field class="form-field" color="accent" id="form-field-region" *ngIf="storageTypeId==='AmazonS3'">
<mat-label>Region</mat-label>
<mat-select [(ngModel)]="param1">
<mat-option *ngFor="let awsRegion of awsRegions" [value]="awsRegion">
{{awsRegion}}
</mat-option>
</mat-select>
</mat-form-field>
</div>

<div>
<mat-form-field class="form-field" color="accent" id="form-field-param1" *ngIf="storageTypeId==='AzureStorage'">
<mat-label >Account</mat-label>
<input [(ngModel)]="param1" matInput>
</mat-form-field>
</div>

<div>
<mat-form-field class="form-field" color="accent" id="form-field-param2">
<mat-label *ngIf="storageTypeId==='AmazonS3'">Bucket</mat-label>
<mat-label *ngIf="storageTypeId==='AzureStorage'">Container Name</mat-label>
<input [(ngModel)]="param2" matInput>
</mat-form-field>
</div>
</mat-dialog-content>

<mat-dialog-actions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@ import {StorageType} from '../../models/storage-type';
export class CatalogBrowserTransferDialog implements OnInit {

name: string = '';
storageTypeId = '';
storageTypeId: string = 'AzureStorage';

// Azure Account or AWS Region (dependent on selected storage type)
param1: string = '';

// Azure Container or AWS S3 Bucket (dependent on selected storage type)
param2: string = '';

constructor(@Inject('STORAGE_TYPES') public storageTypes: StorageType[],
@Inject('AWS_REGIONS') public awsRegions: string[],
private dialogRef: MatDialogRef<CatalogBrowserTransferDialog>,
@Inject(MAT_DIALOG_DATA) contractDefinition?: any) {
}
Expand All @@ -23,7 +30,7 @@ export class CatalogBrowserTransferDialog implements OnInit {


onTransfer() {
this.dialogRef.close({storageTypeId: this.storageTypeId});
this.dialogRef.close({storageTypeId: this.storageTypeId, param1 : this.param1, param2 : this.param2});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,28 @@ export class ContractViewerComponent implements OnInit {

dialogRef.afterClosed().pipe(first()).subscribe(result => {
const storageTypeId: string = result.storageTypeId;
if (storageTypeId !== 'AzureStorage') {
this.notificationService.showError("Only storage type \"AzureStorage\" is implemented currently!")
return;
}
this.createTransferRequest(contract, storageTypeId)
if (storageTypeId == 'AmazonS3') {
const region: string = result.param1;
const bucket: string = result.param2;
this.createTransferRequests3(contract, storageTypeId, region, bucket)
.pipe(switchMap(trq => this.transferService.initiateTransfer(trq)))
.subscribe(transferId => {
this.startPolling(transferId, contract.id!);
}, error => {
console.error(error);
this.notificationService.showError("Error initiating transfer");
});
}else if (storageTypeId == 'AzureStorage'){
this.createTransferRequest(contract, storageTypeId)
.pipe(switchMap(trq => this.transferService.initiateTransfer(trq)))
.subscribe(transferId => {
this.startPolling(transferId, contract.id!);
}, error => {
console.error(error);
this.notificationService.showError("Error initiating transfer");
});
}

});
}

Expand All @@ -94,27 +104,77 @@ export class ContractViewerComponent implements OnInit {
}

private createTransferRequest(contract: ContractAgreementDto, storageTypeId: string): Observable<TransferRequestDto> {
return this.getOfferedAssetForId(contract.assetId!).pipe(map(offeredAsset => {
return {
assetId: offeredAsset.id,
contractId: contract.id,
connectorId: "consumer", //doesn't matter, but cannot be null
dataDestination: {
properties: {
"type": storageTypeId,
account: this.homeConnectorStorageAccount, // CAUTION: hardcoded value for AzureBlob
// container: omitted, so it will be auto-assigned by the EDC runtime
}
},
managedResources: true,
transferType: {isFinite: true}, //must be there, otherwise NPE on backend
connectorAddress: offeredAsset.originator,
protocol: 'ids-multipart'
};
}));
return this.getOfferedAssetForId(contract.assetId!).pipe(map(offeredAsset => {
return {
assetId: offeredAsset.id,
contractId: contract.id,
connectorId: "consumer", //doesn't matter, but cannot be null
dataDestination: {
properties: {
"type": storageTypeId,
account: this.homeConnectorStorageAccount, // CAUTION: hardcoded value for AzureBlob
// container: omitted, so it will be auto-assigned by the EDC runtime
}
},
managedResources: true,
transferType: {isFinite: true}, //must be there, otherwise NPE on backend
connectorAddress: offeredAsset.originator,
protocol: 'ids-multipart'
};
}));


}

private createTransferRequests3(contract: ContractAgreementDto, storageTypeId: string, region: string, bucket: string): Observable<TransferRequestDto> {

if (region && bucket) {
return this.getOfferedAssetForId(contract.assetId!).pipe(map(offeredAsset => {
return {
assetId: offeredAsset.id,
contractId: contract.id,
connectorId: "consumer", //doesn't matter, but cannot be null
dataDestination: {
properties: {
type: "AmazonS3",
region: region,
bucketName: bucket,
},
type: "AmazonS3"
},
managedResources: true,
transferType: {
isFinite: true
}, //must be there, otherwise NPE on backend
connectorAddress: offeredAsset.originator,
protocol: 'ids-multipart'
};
}));
}else{
return this.getOfferedAssetForId(contract.assetId!).pipe(map(offeredAsset => {
return {
assetId: offeredAsset.id,
contractId: contract.id,
connectorId: "consumer", //doesn't matter, but cannot be null
dataDestination: {
properties: {
type: "AmazonS3",
region: "eu-west-1",
},
type: "AmazonS3"
},
managedResources: true,
transferType: {
isFinite: true
}, //must be there, otherwise NPE on backend
connectorAddress: offeredAsset.originator,
protocol: 'ids-multipart'
};
}));
}

}

/**
* This method is used to obtain that URL of the connector that is offering a particular asset from the catalog.
* This is a bit of a hack, because currently there is no "clean" way to get the counter-party's URL for a ContractAgreement.
Expand Down