├── gradle.properties
├── s3-artifact-storage-common
├── src
│ ├── test
│ │ ├── resources
│ │ │ └── S3UtilsTest
│ │ │ │ ├── file.txt
│ │ │ │ ├── file.css
│ │ │ │ ├── file.htm
│ │ │ │ ├── file.html
│ │ │ │ ├── file.bin
│ │ │ │ ├── file.jpg
│ │ │ │ └── file.zip
│ │ └── java
│ │ │ ├── testng.xml
│ │ │ └── jetbrains
│ │ │ └── buildServer
│ │ │ └── artifacts
│ │ │ └── s3
│ │ │ └── S3UtilTest.java
│ └── main
│ │ └── java
│ │ └── jetbrains
│ │ └── buildServer
│ │ └── artifacts
│ │ └── s3
│ │ └── S3ArtifactUtil.java
└── build.gradle
├── s3-artifact-storage-ui
├── .eslintignore
├── .gitignore
├── .prettierrc
├── .npmrc
├── .babelrc
├── src
│ ├── types
│ │ ├── declarations.d.ts
│ │ └── global.d.ts
│ ├── index.tsx
│ ├── App
│ │ ├── MultipartUpload
│ │ │ ├── components
│ │ │ │ ├── CustomizeUpload.tsx
│ │ │ │ ├── PartSize.tsx
│ │ │ │ └── Threshold.tsx
│ │ │ └── MultipartUploadSection.tsx
│ │ ├── S3
│ │ │ ├── components
│ │ │ │ ├── IAMRole.tsx
│ │ │ │ └── DefaultProviderChain.tsx
│ │ │ └── TransferSpeedUp
│ │ │ │ └── components
│ │ │ │ ├── UploadDistribution.tsx
│ │ │ │ ├── DownloadDistribution.tsx
│ │ │ │ └── Distribution.tsx
│ │ ├── components
│ │ │ ├── BucketPrefix.tsx
│ │ │ ├── Bucket.tsx
│ │ │ └── StorageTypeChangedWarningDialog.tsx
│ │ ├── Storage
│ │ │ ├── StorageSection.tsx
│ │ │ └── components
│ │ │ │ ├── StorageId.tsx
│ │ │ │ ├── StorageName.tsx
│ │ │ │ └── StorageType.tsx
│ │ ├── S3Compatible
│ │ │ ├── S3Section.tsx
│ │ │ └── components
│ │ │ │ ├── AccessKeyId.tsx
│ │ │ │ ├── SecretAccessKey.tsx
│ │ │ │ └── Endpoint.tsx
│ │ ├── ProtocolSettings
│ │ │ └── ProtocolSettings.tsx
│ │ └── styles.css
│ ├── hooks
│ │ ├── useStorageOptions.tsx
│ │ ├── useCanLoadBucketInfoData.tsx
│ │ ├── useBucketOptions.tsx
│ │ ├── useBucketLocation.tsx
│ │ └── useTransferAccelerationAvailable.tsx
│ ├── Utilities
│ │ ├── fetchHelper.ts
│ │ ├── fetchBucketNames.ts
│ │ ├── fetchBucketLocation.ts
│ │ ├── fetchS3TransferAccelerationAvailability.ts
│ │ ├── fetchPublicKeys.ts
│ │ ├── responseParser.ts
│ │ ├── fetchCfKeysValidationResult.ts
│ │ └── fetchDistributions.ts
│ └── contexts
│ │ └── AppContext.tsx
├── third-party-licenses-json.js
├── tsconfig.json
└── webpack.config.js
├── s3-artifact-storage-server
├── src
│ ├── main
│ │ ├── resources
│ │ │ ├── buildServerResources
│ │ │ │ ├── .gitignore
│ │ │ │ └── s3_storage_settings.jsp
│ │ │ └── META-INF
│ │ │ │ └── build-server-plugin-s3-storage.xml
│ │ └── java
│ │ │ └── jetbrains
│ │ │ └── buildServer
│ │ │ ├── artifacts
│ │ │ └── s3
│ │ │ │ ├── cleanup
│ │ │ │ ├── CleanupListener.java
│ │ │ │ └── AbstractCleanupListener.java
│ │ │ │ ├── S3CompatibleArtifactContentProvider.java
│ │ │ │ ├── orphans
│ │ │ │ ├── OrphanedArtifacts.java
│ │ │ │ ├── BuildEntry.java
│ │ │ │ ├── BuildTypeEntry.java
│ │ │ │ ├── OrphanedArtifact.java
│ │ │ │ └── ProjectEntry.java
│ │ │ │ ├── web
│ │ │ │ └── S3CompatibleArtifactDownloadProcessor.java
│ │ │ │ ├── util
│ │ │ │ ├── ParamUtil.java
│ │ │ │ └── RegionSortPriority.java
│ │ │ │ └── settings
│ │ │ │ ├── S3PropertiesProcessor.java
│ │ │ │ └── CloudFrontPropertiesProcessor.java
│ │ │ └── filestorage
│ │ │ └── cloudfront
│ │ │ └── GuardedCloudFrontPresignedUrlProvider.java
│ └── test
│ │ └── java
│ │ └── testng-docker-testcontainers.xml
├── teamcity-plugin.xml
├── build.gradle
└── kotlin-dsl
│ ├── S3CommonSettings.xml
│ └── S3CompatibleStorageSettings.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── teamcity-s3-sdk
├── src
│ ├── main
│ │ └── java
│ │ │ └── jetbrains
│ │ │ └── buildServer
│ │ │ └── artifacts
│ │ │ └── s3
│ │ │ ├── S3Dto.java
│ │ │ ├── publish
│ │ │ ├── presigned
│ │ │ │ ├── upload
│ │ │ │ │ ├── PublishingInterruptedException.java
│ │ │ │ │ ├── PresignedUrlsProviderClientFactory.java
│ │ │ │ │ ├── TeamCityServerPresignedUrlsProviderClientFactory.java
│ │ │ │ │ ├── PresignedUploadProgressListener.java
│ │ │ │ │ └── PresignedUrlsProviderClient.java
│ │ │ │ └── util
│ │ │ │ │ ├── Throwables.java
│ │ │ │ │ ├── CloseableS3SignedUrlUploadPool.java
│ │ │ │ │ ├── RepeatableFilePartRequestEntityApacheLegacy.java
│ │ │ │ │ ├── S3MultipartUploadFileSplitter.java
│ │ │ │ │ ├── RepeatableFilePartRequestEntityApache43.java
│ │ │ │ │ ├── DigestUtil.java
│ │ │ │ │ └── S3ErrorDto.java
│ │ │ ├── logger
│ │ │ │ ├── S3UploadLogger.java
│ │ │ │ ├── S3Log4jUploadLogger.java
│ │ │ │ └── CompositeS3UploadLogger.java
│ │ │ ├── errors
│ │ │ │ ├── ResponseAdapter.java
│ │ │ │ ├── HttpResponseErrorHandler.java
│ │ │ │ ├── HttpResponseAdapter.java
│ │ │ │ ├── TeamCityPresignedUrlsProviderErrorHandler.java
│ │ │ │ ├── S3ServerResponseErrorHandler.java
│ │ │ │ └── S3DirectResponseErrorHandler.java
│ │ │ ├── S3FileUploaderFactory.java
│ │ │ └── S3FileUploaderFactoryImpl.java
│ │ │ ├── amazonClient
│ │ │ ├── WithS3Client.java
│ │ │ ├── WithS3Presigner.java
│ │ │ ├── WithCloudFrontClient.java
│ │ │ └── AmazonS3Provider.java
│ │ │ ├── cloudfront
│ │ │ ├── CloudFrontUtils.java
│ │ │ ├── RequestMetadata.java
│ │ │ ├── CloudFrontPresignedUrlProvider.java
│ │ │ ├── CloudFrontSettings.java
│ │ │ ├── CloudFrontEnabledPresignedUrlProvider.java
│ │ │ └── CloudFrontConstants.java
│ │ │ ├── serialization
│ │ │ ├── XmlSerializer.java
│ │ │ ├── impl
│ │ │ │ ├── JDomElementDeserializer.java
│ │ │ │ └── XmlSerializerImpl.java
│ │ │ └── S3XmlSerializerFactory.java
│ │ │ ├── PresignedUrlWithTtl.java
│ │ │ ├── S3Settings.java
│ │ │ ├── exceptions
│ │ │ ├── InvalidSettingsException.java
│ │ │ └── FileUploadFailedException.java
│ │ │ ├── transport
│ │ │ ├── MultipartUploadStartRequestDto.java
│ │ │ ├── PresignedUrlPartDto.java
│ │ │ ├── MultipartUploadAbortRequestDto.java
│ │ │ ├── MultipartUploadCompleteRequestDto.java
│ │ │ ├── PresignedUrlListResponseDto.java
│ │ │ ├── AmazonServiceErrorDto.java
│ │ │ └── PresignedUrlDto.java
│ │ │ ├── FileUploadInfo.java
│ │ │ ├── SSLParamUtil.java
│ │ │ ├── S3ClientResourceFetcher.java
│ │ │ ├── S3PresignedUrlProvider.java
│ │ │ ├── S3Configuration.java
│ │ │ └── CheckS3TransferAccelerationAvailability.java
│ └── test
│ │ └── java
│ │ ├── testng.xml
│ │ └── jetbrains
│ │ └── buildServer
│ │ └── artifacts
│ │ └── s3
│ │ └── S3DtoSerializerTest.java
└── build.gradle
├── s3-artifact-storage-agent
├── src
│ ├── test
│ │ ├── resources
│ │ │ └── artifacts
│ │ │ │ └── file.zip
│ │ └── java
│ │ │ ├── testng.xml
│ │ │ └── jetbrains
│ │ │ └── buildServer
│ │ │ └── artifacts
│ │ │ └── s3
│ │ │ ├── publish
│ │ │ └── presigned
│ │ │ │ └── util
│ │ │ │ └── S3MultipartUploadFileSplitterTest.java
│ │ │ └── download
│ │ │ └── S3MockContainer.java
│ └── main
│ │ ├── java
│ │ └── jetbrains
│ │ │ └── buildServer
│ │ │ └── artifacts
│ │ │ └── s3
│ │ │ ├── download
│ │ │ ├── IORunnable.java
│ │ │ ├── parallel
│ │ │ │ ├── splitter
│ │ │ │ │ ├── FileSplitter.java
│ │ │ │ │ └── SplitabilityReport.java
│ │ │ │ ├── PartFailure.java
│ │ │ │ ├── strategy
│ │ │ │ │ └── ParallelDownloadStrategy.java
│ │ │ │ ├── FilePart.java
│ │ │ │ ├── ParallelDownloadState.java
│ │ │ │ └── ParallelDownloadContext.java
│ │ │ └── S3HttpClient.java
│ │ │ ├── publish
│ │ │ ├── logger
│ │ │ │ └── BuildLoggerS3Logger.java
│ │ │ ├── SettingsProcessor.java
│ │ │ └── S3CompatibleArtifactsPublisher.java
│ │ │ └── S3AdditionalHeadersProvider.java
│ │ └── resources
│ │ └── META-INF
│ │ └── build-agent-plugin-s3-storage.xml
├── teamcity-plugin.xml
└── build.gradle
├── .gitignore
├── settings.gradle
├── .editorconfig
├── lens-integration
├── build.gradle
└── src
│ ├── main
│ └── java
│ │ └── jetbrains
│ │ └── buildServer
│ │ └── artifacts
│ │ └── s3
│ │ └── lens
│ │ └── integration
│ │ ├── LensIntegrationService.java
│ │ ├── LensResponseErrorHandler.java
│ │ ├── dto
│ │ └── UploadInfoEvent.java
│ │ └── JsonEntityProducer.java
│ └── test
│ └── java
│ └── jetbrains
│ └── buildServer
│ └── artifacts
│ └── s3
│ └── lens
│ └── integration
│ └── TestJsonGeneration.java
├── modules
├── s3-artifact-storage-common.iml
├── lens-integration.iml
├── s3-artifact-storage-agent.iml
└── teamcity-s3-sdk.iml
└── gradlew.bat
/gradle.properties:
--------------------------------------------------------------------------------
1 | jacksonVersion=2.14.3
2 |
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.txt:
--------------------------------------------------------------------------------
1 | My file
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | !.eslintrc.js
3 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | yarn-error.log
3 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true
3 | }
4 |
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | body {
4 | padding: 0;
5 | }
6 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/.npmrc:
--------------------------------------------------------------------------------
1 | @jetbrains-internal:registry= https://packages.jetbrains.team/npm/p/tc/teamcity-npm
2 |
--------------------------------------------------------------------------------
/s3-artifact-storage-server/src/main/resources/buildServerResources/.gitignore:
--------------------------------------------------------------------------------
1 | bundle-report.html
2 | bundle.js
3 | bundle.js.LICENSE.txt
4 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/teamcity-s3-artifact-storage-plugin/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/S3Dto.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3;
2 |
3 | public interface S3Dto {
4 | }
5 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["@babel/preset-env", "@babel/preset-react", "@babel/preset-typescript"],
3 | "plugins": [
4 | ["@babel/transform-runtime"]
5 | ]
6 | }
--------------------------------------------------------------------------------
/s3-artifact-storage-agent/src/test/resources/artifacts/file.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/teamcity-s3-artifact-storage-plugin/HEAD/s3-artifact-storage-agent/src/test/resources/artifacts/file.zip
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/teamcity-s3-artifact-storage-plugin/HEAD/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.bin
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/teamcity-s3-artifact-storage-plugin/HEAD/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.jpg
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/teamcity-s3-artifact-storage-plugin/HEAD/s3-artifact-storage-common/src/test/resources/S3UtilsTest/file.zip
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .idea/
3 | target/
4 | s3-artifact-storage-agent/out/*
5 | s3-artifact-storage-common/out/*
6 | s3-artifact-storage-server/out/*
7 | .gradle/*
8 | build/
9 | .DS_Store
10 | local-repo
11 | local-aws-repo
12 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 's3-artifact-storage'
2 |
3 | include 's3-artifact-storage-agent'
4 | include 's3-artifact-storage-common'
5 | include 's3-artifact-storage-server'
6 | include 'teamcity-s3-sdk'
7 | include 'lens-integration'
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # top-most EditorConfig file
2 | root = true
3 |
4 | # Unix-style newlines with a newline ending every file
5 | [*]
6 | end_of_line = lf
7 | insert_final_newline = true
8 | indent_style = space
9 |
10 | [*.java]
11 | indent_size = 2
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/s3-artifact-storage-agent/src/main/java/jetbrains/buildServer/artifacts/s3/download/IORunnable.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.download;
2 |
3 | import java.io.IOException;
4 |
5 | public interface IORunnable {
6 | void run() throws IOException;
7 | }
8 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/types/declarations.d.ts:
--------------------------------------------------------------------------------
1 | declare module '@jetbrains/logos/*';
2 | declare module '@jetbrains/icons/*';
3 |
4 | declare module '*.css' {
5 | const content: { readonly [className: string]: string };
6 | export default content;
7 | }
8 |
9 | declare module '*.svg';
10 |
--------------------------------------------------------------------------------
/s3-artifact-storage-server/src/main/java/jetbrains/buildServer/artifacts/s3/cleanup/CleanupListener.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.cleanup;
2 |
3 | public interface CleanupListener {
4 | void onError(Exception exception, boolean isRecoverable);
5 | void onSuccess(String objectKey);
6 | }
7 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/test/java/testng.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/index.tsx:
--------------------------------------------------------------------------------
1 | import { React, ReactDOM } from '@jetbrains/teamcity-api';
2 |
3 | import App from './App/App';
4 | import { Config } from './types';
5 |
6 | global.renderEditS3Storage = (config: Config) => {
7 | ReactDOM.render(
8 | ,
9 | document.getElementById('edit-s3-storage-root')
10 | );
11 | };
12 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/third-party-licenses-json.js:
--------------------------------------------------------------------------------
1 | module.exports = ({modules}) =>
2 | JSON.stringify(
3 | modules.map(({license, ...rest}) => ({
4 | ...rest,
5 | license: license.name,
6 | licenseUrl: license.url,
7 | })),
8 | null,
9 | // eslint-disable-next-line no-magic-numbers
10 | 2,
11 | )
12 |
--------------------------------------------------------------------------------
/s3-artifact-storage-server/src/test/java/testng-docker-testcontainers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/s3-artifact-storage-server/src/main/java/jetbrains/buildServer/artifacts/s3/cleanup/AbstractCleanupListener.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.cleanup;
2 |
3 | public class AbstractCleanupListener implements CleanupListener{
4 | @Override
5 | public void onError(Exception exception, boolean isRecoverable) {
6 | }
7 |
8 | @Override
9 | public void onSuccess(String objectKey) {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./node_modules/@jetbrains/teamcity-api/plugin.tsconfig.json",
3 | "include": [
4 | "./src/**/*"
5 | ],
6 | "compilerOptions": {
7 | "strict": true,
8 | "esModuleInterop": true,
9 | "lib": [
10 | "dom",
11 | "es2015"
12 | ],
13 | "jsx": "react-jsx",
14 | "typeRoots": ["./node_modules/@types", "./src/types"]
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/s3-artifact-storage-agent/teamcity-plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/publish/presigned/upload/PublishingInterruptedException.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.publish.presigned.upload;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | public class PublishingInterruptedException extends RuntimeException {
6 | public PublishingInterruptedException(@NotNull final String reason) {
7 | super(reason);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/amazonClient/WithS3Client.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.amazonClient;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 | import software.amazon.awssdk.services.s3.S3Client;
6 |
7 | public interface WithS3Client {
8 | @Nullable
9 | T execute(@NotNull S3Client client) throws E;
10 | }
11 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/publish/logger/S3UploadLogger.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.publish.logger;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | public interface S3UploadLogger {
6 | void debug(@NotNull String message);
7 |
8 | void info(@NotNull String message);
9 |
10 | void warn(@NotNull String message);
11 |
12 | void error(@NotNull String message);
13 | }
14 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/publish/errors/ResponseAdapter.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.publish.errors;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 |
6 | public interface ResponseAdapter {
7 |
8 | @Nullable
9 | String getHeader(@NotNull final String header);
10 |
11 | @Nullable
12 | String getResponse();
13 |
14 | int getStatusCode();
15 | }
16 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/amazonClient/WithS3Presigner.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.amazonClient;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 | import org.jetbrains.annotations.Nullable;
5 | import software.amazon.awssdk.services.s3.presigner.S3Presigner;
6 |
7 | public interface WithS3Presigner {
8 | @Nullable
9 | T execute(@NotNull S3Presigner presigner) throws E;
10 | }
11 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/cloudfront/CloudFrontUtils.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.cloudfront;
2 |
3 | public class CloudFrontUtils {
4 |
5 | public enum Protocol {
6 | http,
7 | https
8 | }
9 |
10 | public static String generateResourcePath(Protocol protocol, String distributionDomain, String resourcePath) {
11 | return protocol + "://" + distributionDomain + "/" + resourcePath;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/lens-integration/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 |
5 | dependencies {
6 | implementation project(':teamcity-s3-sdk')
7 |
8 | compileOnly "org.jetbrains.teamcity:agent-openapi:${teamcityVersion}"
9 | compileOnly "org.jetbrains.teamcity:web-openapi:${teamcityVersion}"
10 | testImplementation "org.testng:testng:6.8.21"
11 | testImplementation "org.jetbrains.teamcity:tests-support:${teamcityVersion}"
12 | testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.12.1'
13 | }
14 |
--------------------------------------------------------------------------------
/s3-artifact-storage-agent/src/main/java/jetbrains/buildServer/artifacts/s3/download/parallel/splitter/FileSplitter.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.download.parallel.splitter;
2 |
3 | import java.util.List;
4 | import jetbrains.buildServer.artifacts.s3.download.parallel.FilePart;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | public interface FileSplitter {
8 |
9 | @NotNull
10 | List split(long fileSize);
11 |
12 | @NotNull
13 | SplitabilityReport testSplitability(long fileSize);
14 | }
15 |
--------------------------------------------------------------------------------
/s3-artifact-storage-common/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java-library'
3 | }
4 |
5 | dependencies {
6 | compileOnly "org.jetbrains.teamcity:common-api:${teamcityVersion}"
7 | api project(':teamcity-s3-sdk')
8 | testImplementation "org.testng:testng:6.8.21"
9 | testImplementation "org.jetbrains.teamcity:tests-support:${teamcityVersion}"
10 | testImplementation group: 'org.mockito', name: 'mockito-core', version: '3.12.1'
11 | testImplementation("org.jetbrains.teamcity.plugins:aws-core-common:$awsCoreVersion") {
12 | changing = true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/serialization/XmlSerializer.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.serialization;
2 |
3 |
4 | import com.fasterxml.jackson.core.JsonProcessingException;
5 | import org.jdom.Element;
6 | import org.jetbrains.annotations.NotNull;
7 |
8 | public interface XmlSerializer {
9 |
10 | String serialize(@NotNull Object object) throws JsonProcessingException;
11 |
12 | Element serializeAsElement(@NotNull Object object);
13 |
14 | T deserialize(@NotNull String xml, @NotNull Class clazz);
15 | }
16 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/PresignedUrlWithTtl.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3;
2 |
3 | import org.jetbrains.annotations.NotNull;
4 |
5 | public class PresignedUrlWithTtl {
6 | private final String url;
7 | private final int urlTtlSeconds;
8 |
9 | public PresignedUrlWithTtl(@NotNull String url, int urlTtlSeconds) {
10 | this.url = url;
11 | this.urlTtlSeconds = urlTtlSeconds;
12 | }
13 |
14 | public String getUrl() {
15 | return url;
16 | }
17 |
18 | public int getUrlTtlSeconds() {
19 | return urlTtlSeconds;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/amazonClient/WithCloudFrontClient.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.amazonClient;
2 |
3 | import jetbrains.buildServer.serverSide.connections.credentials.ConnectionCredentialsException;
4 | import org.jetbrains.annotations.NotNull;
5 | import org.jetbrains.annotations.Nullable;
6 | import software.amazon.awssdk.services.cloudfront.CloudFrontClient;
7 |
8 | public interface WithCloudFrontClient {
9 | @Nullable
10 | T execute(@NotNull CloudFrontClient client) throws E, ConnectionCredentialsException;
11 | }
12 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/App/MultipartUpload/components/CustomizeUpload.tsx:
--------------------------------------------------------------------------------
1 | import { React } from '@jetbrains/teamcity-api';
2 | import { FormCheckbox } from '@jetbrains-internal/tcci-react-ui-components';
3 | import { useFormContext } from 'react-hook-form';
4 |
5 | import { FormFields } from '../../appConstants';
6 |
7 | export default function CustomizeUpload() {
8 | const { control } = useFormContext();
9 | return (
10 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/types/global.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 |
3 | declare global {
4 | function renderEditS3Storage(config: ConfigWrapper): void;
5 |
6 | interface Window {
7 | BS: {
8 | Encrypt: {
9 | encryptData: (value: string, publicKey: string) => string;
10 | };
11 | Util: {
12 | showHelp: (
13 | event: React.MouseEvent,
14 | href: string,
15 | { width: number, height: number }
16 | ) => void;
17 | };
18 | };
19 | $j: JQueryStatic;
20 | __secretKey: string | null | undefined;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/App/S3/components/IAMRole.tsx:
--------------------------------------------------------------------------------
1 | import { React } from '@jetbrains/teamcity-api';
2 | import {
3 | FormInput,
4 | FormRow,
5 | } from '@jetbrains-internal/tcci-react-ui-components';
6 |
7 | import { useFormContext } from 'react-hook-form';
8 |
9 | import { IFormInput } from '../../../types';
10 | import { FormFields } from '../../appConstants';
11 |
12 | export default function IAMRole() {
13 | const { control } = useFormContext();
14 | return (
15 |
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/App/components/BucketPrefix.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | FormInput,
3 | FormRow,
4 | } from '@jetbrains-internal/tcci-react-ui-components';
5 | import { React } from '@jetbrains/teamcity-api';
6 | import { useFormContext } from 'react-hook-form';
7 |
8 | import { FormFields } from '../appConstants';
9 |
10 | export default function BucketPrefix() {
11 | const { control } = useFormContext();
12 | return (
13 |
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/s3-artifact-storage-common/src/test/java/testng.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/teamcity-s3-sdk/src/main/java/jetbrains/buildServer/artifacts/s3/publish/presigned/upload/PresignedUrlsProviderClientFactory.java:
--------------------------------------------------------------------------------
1 | package jetbrains.buildServer.artifacts.s3.publish.presigned.upload;
2 |
3 | import java.util.Collection;
4 | import jetbrains.buildServer.artifacts.ArtifactTransportAdditionalHeadersProvider;
5 | import org.jetbrains.annotations.NotNull;
6 |
7 | public interface PresignedUrlsProviderClientFactory {
8 | PresignedUrlsProviderClient createClient(@NotNull final TeamCityConnectionConfiguration connectionConfiguration,
9 | @NotNull Collection additionalHeadersProviders);
10 | }
11 |
--------------------------------------------------------------------------------
/s3-artifact-storage-server/src/main/resources/buildServerResources/s3_storage_settings.jsp:
--------------------------------------------------------------------------------
1 |
2 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
3 | <%@ taglib prefix="intprop" uri="/WEB-INF/functions/intprop" %>
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/s3-artifact-storage-ui/src/hooks/useStorageOptions.tsx:
--------------------------------------------------------------------------------
1 | import { Option } from '@jetbrains-internal/tcci-react-ui-components';
2 |
3 | import { useAppContext } from '../contexts/AppContext';
4 |
5 | export default function useStorageOptions() {
6 | const config = useAppContext();
7 |
8 | const storageTypes = config.storageTypes
9 | .split(/[\[\],]/)
10 | .map((it) => it.trim())
11 | .filter((it) => !!it);
12 | const storageNames = config.storageNames
13 | .split(/[\[\],]/)
14 | .map((it) => it.trim())
15 | .filter((it) => !!it);
16 | return storageTypes.reduce