All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.twonote.rgwadmin4j.impl.RgwAdminImpl Maven / Gradle / Ivy

There is a newer version: 2.0.9
Show newest version
package org.twonote.rgwadmin4j.impl;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import okhttp3.*;
import org.twonote.rgwadmin4j.RgwAdmin;
import org.twonote.rgwadmin4j.model.*;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Radosgw administrator implementation
 *
 * 

Created by petertc on 2/16/17. */ public class RgwAdminImpl implements RgwAdmin { private static final Gson gson = new Gson(); private static final JsonParser jsonParser = new JsonParser(); private static final RequestBody emptyBody = RequestBody.create(null, new byte[] {}); private final String endpoint; private final OkHttpClient client; /** * Create a Radosgw administrator implementation * * @param accessKey Access key of the admin who have proper administrative capabilities. * @param secretKey Secret key of the admin who have proper administrative capabilities. * @param endpoint Radosgw admin API endpoint, e.g., http://127.0.0.1:80/admin */ public RgwAdminImpl(String accessKey, String secretKey, String endpoint) { validEndpoint(endpoint); this.client = new OkHttpClient().newBuilder().addInterceptor(new S3Auth(accessKey, secretKey)).build(); this.endpoint = endpoint; } private static void validEndpoint(String endpoint) { if (HttpUrl.parse(endpoint) == null) { throw new IllegalArgumentException("endpoint is invalid"); } } private static void appendParameters(Map parameters, HttpUrl.Builder urlBuilder) { if (parameters != null) { parameters.forEach(urlBuilder::addQueryParameter); } } private static String absSubUserId(String userId, String subUserId) { return String.join(":", userId, subUserId); } private static Type setModelAndGetCorrespondingList2(Class type) { return new TypeToken>() {}.where(new TypeParameter() {}, type).getType(); } @Override public void trimUserUsage(String userId, Map parameters) { if (parameters == null) { parameters = new HashMap<>(); } parameters.put("uid", userId); trimUsage(parameters); } @Override public void trimUsage(Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint).newBuilder().addPathSegment("usage"); if (parameters == null) { parameters = new HashMap<>(); } parameters.put("remove-all", "True"); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().delete().url(urlBuilder.build()).build(); safeCall(request); } @Override public Optional getUserUsage(String userId) { return getUserUsage(userId, null); } @Override public Optional getUserUsage(String userId, Map parameters) { if (parameters == null) { parameters = new HashMap<>(); } parameters.put("uid", userId); return getUsage(parameters); } @Override public Optional getUsage() { return getUsage(null); } @Override public Optional getUsage(Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint).newBuilder().addPathSegment("usage"); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); return Optional.ofNullable(gson.fromJson(resp, UsageInfo.class)); } @Override public List addUserCapability(String userId, List userCaps) { Request request = new Request.Builder() .put(emptyBody) .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("caps") .addQueryParameter("uid", userId) .addQueryParameter("user-caps", Joiner.on(";").join(userCaps)) .build()) .build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } @Override public List removeUserCapability(String userId, List userCaps) { Request request = new Request.Builder() .delete() .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("caps") .addQueryParameter("uid", userId) .addQueryParameter("user-caps", Joiner.on(";").join(userCaps)) .build()) .build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } @Override public List createSubUser( String userId, String subUserId, Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("subuser") .addQueryParameter("uid", userId) .addQueryParameter("subuser", subUserId); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().put(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } @Override public SubUser createSubUser( String userId, String subUserId, SubUser.Permission permission, CredentialType credentialType) { List subUser = createSubUser( userId, subUserId, ImmutableMap.of( "access", permission.toString(), "key-type", credentialType.toString(), "generate-secret", "True")); String absSubUserId = absSubUserId(userId, subUserId); return subUser.stream().filter(u -> absSubUserId.equals(u.getId())).findFirst().get(); } public List modifySubUser( String userId, String subUserId, Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("subuser") .addQueryParameter("uid", userId) .addQueryParameter("subuser", subUserId); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().post(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } @Override public List setSubUserPermission( String userId, String subUserId, SubUser.Permission permission) { return modifySubUser(userId, subUserId, ImmutableMap.of("access", permission.toString())); } @Override public List listSubUserInfo(String userId) { Optional userInfo = getUserInfo(userId); if (userInfo.isPresent()) { return userInfo.get().getSubusers(); } else { return new ArrayList<>(); } } @Override public Optional getSubUserInfo(String userId, String subUserId) { String absSubUserId = absSubUserId(userId, subUserId); List subUsers = listSubUserInfo(userId); return subUsers.stream().filter(u -> absSubUserId.equals(u.getId())).findFirst(); } @Override public void removeSubUser(String userId, String subUserId) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("subuser") .addQueryParameter("uid", userId) .addQueryParameter("subuser", subUserId); Request request = new Request.Builder().delete().url(urlBuilder.build()).build(); safeCall(request); } private List _createKey(String uid, Map parameters, Class returnModel) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("key") .addQueryParameter("uid", uid); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().put(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); // Fit luminous behavior if (resp == null) { throw new RgwAdminException(404, "NoSuchUser"); } Type type = setModelAndGetCorrespondingList2(returnModel); return gson.fromJson(resp, type); } private List _createKey(String uid, Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("key") .addQueryParameter("uid", uid); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().put(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } private void _removeKey(String uid, Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("key") .addQueryParameter("uid", uid); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().delete().url(urlBuilder.build()).build(); String resp = safeCall(request); // Fit luminous behavior if (resp == null) { throw new RgwAdminException(404, "NoSuchUser"); } } @Override public List createS3Credential(String userId, String accessKey, String secretKey) { return _createKey( userId, ImmutableMap.of( "access-key", accessKey, "secret-key", secretKey), S3Credential.class); } @Override public List createS3Credential(String userId) { return _createKey(userId, ImmutableMap.of("generate-key", "True"), S3Credential.class); } @Override public void removeS3Credential(String userId, String accessKey) { _removeKey(userId, ImmutableMap.of("access-key", accessKey)); } @Override public List createS3CredentialForSubUser( String userId, String subUserId, String accessKey, String secretKey) { List s3Credentials = _createKey( userId, ImmutableMap.of( "subuser", subUserId, "access-key", accessKey, "secret-key", secretKey, "key-type", "s3"), S3Credential.class); return s3Credentials .stream() .filter(k -> absSubUserId(userId, subUserId).equals(k.getUserId())) .collect(Collectors.toList()); } @Override public List createS3CredentialForSubUser(String userId, String subUserId) { List s3Credentials = _createKey( userId, ImmutableMap.of( "subuser", subUserId, "key-type", "s3", "generate-key", "True"), S3Credential.class); return s3Credentials .stream() .filter(k -> absSubUserId(userId, subUserId).equals(k.getUserId())) .collect(Collectors.toList()); } @Override public void removeS3CredentialFromSubUser(String userId, String subUserId, String accessKey) { _removeKey( userId, ImmutableMap.of( "subuser", subUserId, "key-type", "s3", "access-key", accessKey)); } @Override public SwiftCredential createSwiftCredentialForSubUser( String userId, String subUserId, String password) { List swiftCredentials = _createKey( userId, ImmutableMap.of( "subuser", subUserId, "secret-key", password, "key-type", "swift"), SwiftCredential.class); return swiftCredentials .stream() .filter(k -> absSubUserId(userId, subUserId).equals(k.getUserId())) .collect(Collectors.toList()) .get(0); } @Override public SwiftCredential createSwiftCredentialForSubUser(String userId, String subUserId) { List swiftCredentials = _createKey( userId, ImmutableMap.of( "subuser", subUserId, "key-type", "swift", "generate-key", "True"), SwiftCredential.class); return swiftCredentials .stream() .filter(k -> absSubUserId(userId, subUserId).equals(k.getUserId())) .collect(Collectors.toList()) .get(0); } @Override public void removeSwiftCredentialFromSubUser(String userId, String subUserId) { _removeKey(userId, ImmutableMap.of("subuser", subUserId, "key-type", "swift")); } /* * The operation is success if the target is not exist in the system after the operation is * executed. The operation does not throw exception even if the target is not exist in the * beginning. */ @Override public void removeBucket(String bucketName) { Request request = new Request.Builder() .delete() .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .addQueryParameter("bucket", bucketName) .addQueryParameter("purge-objects", "true") .build()) .build(); safeCall(request); } @Override public void linkBucket(String bucketName, String bucketId, String userId) { Request request = new Request.Builder() .put(emptyBody) .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .addQueryParameter("bucket", bucketName) .addQueryParameter("bucket-id", bucketId) .addQueryParameter("uid", userId) .build()) .build(); safeCall(request); } @Override public void unlinkBucket(String bucketName, String userId) { Request request = new Request.Builder() .post(emptyBody) .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .addQueryParameter("bucket", bucketName) .addQueryParameter("uid", userId) .build()) .build(); safeCall(request); } @Override public Optional checkBucketIndex( String bucketName, boolean isCheckObjects, boolean isFix) { Request request = new Request.Builder() .get() .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .query("index") .addQueryParameter("bucket", bucketName) .addQueryParameter("check-objects", Boolean.toString(isCheckObjects)) .addQueryParameter("fix", Boolean.toString(isFix)) .build()) .build(); String resp = safeCall(request); return Optional.ofNullable(resp); } @Override public List listBucket(String userId) { Request request = new Request.Builder() .get() .url( HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .addQueryParameter("uid", userId) .addQueryParameter("stats", "False") .build()) .build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } @Override public List listBucketInfo(String userId) { return _getBucketInfo(ImmutableMap.of("uid", userId, "stats", "True")); } private List _getBucketInfo(Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint).newBuilder().addPathSegment("bucket"); appendParameters(parameters, urlBuilder); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); // ugly part... if (parameters.containsKey("uid")) { Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } else if (parameters.containsKey("bucket")) { BucketInfo response = gson.fromJson(resp, BucketInfo.class); List ret = new ArrayList<>(); if (response != null) { ret.add(response); } return ret; } throw new RuntimeException("Parameters should have either uid or bucket"); } @Override public Optional getBucketInfo(String bucketName) { List responses = _getBucketInfo(ImmutableMap.of("bucket", bucketName, "stats", "True")); if (responses.size() == 0) { return Optional.empty(); } else if (responses.size() == 1) { return Optional.of(responses.get(0)); } throw new RuntimeException("Server should not return more than one bucket"); } /** * Guarantee that the request is execute success and the connection is closed * * @param request request * @return resp body in str; null if no body or status code == 404 * @throws RgwAdminException if resp code != (200||404) */ private String safeCall(Request request) { try (Response response = client.newCall(request).execute()) { if (response.code() == 404) { return null; } if (!response.isSuccessful()) { throw ErrorUtils.parseError(response); } ResponseBody body = response.body(); if (body != null) { return response.body().string(); } else { return null; } } catch (IOException e) { throw new RgwAdminException(500, "IOException", e); } } @Override public User createUser(String userId) { return createUser(userId, null); } @Override public User createUser(String userId, Map options) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .addQueryParameter("uid", userId) .addQueryParameter("display-name", userId); appendParameters(options, urlBuilder); Request request = new Request.Builder().put(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); return gson.fromJson(resp, User.class); } @Override public Optional getUserInfo(String userId) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .addQueryParameter("uid", userId); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); return Optional.ofNullable(gson.fromJson(resp, User.class)); } /** * Retrieve keys in a given metadata type * *

Equivalent to radosgw-admin metadata list --metadata-key bucket.instance * * @param metadataType Specify the metadata type. * @return A list of radosgw internal metadata keys in the given metadata type. */ private List listMetadata(MetadataType metadataType) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("metadata") .addPathSegment(metadataType.toString()); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); Type type = new TypeToken>() {}.getType(); return gson.fromJson(resp, type); } /** * Retrieve radosgw internal metadata content. * *

Equivalent to radosgw-admin metadata get --metadata-key bucket.instance:dsvdvdsv * * @param metadataType Specify the metadata type. * @param key Specify the metadata key. * @return Content of metadata in a json string. */ private T getMetadata(MetadataType metadataType, String key, Class returnType) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("metadata") .addQueryParameter("key", String.join(":", metadataType.toString(), key)); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); JsonObject jo = (JsonObject)jsonParser.parse(resp); return gson.fromJson(jo.get("data").toString(), returnType); } @Override public List listUser() { return listMetadata(MetadataType.USER); } @Override public List listSubUser(String userId) { return listSubUserInfo(userId).stream().map(s -> s.getId()).collect(Collectors.toList()); } @Override public List listUserInfo() { List userIds = listMetadata(MetadataType.USER); return userIds .stream() .map(i -> getMetadata(MetadataType.USER, i, User.class)) .collect(Collectors.toList()); } @Override public User modifyUser(String userId, Map parameters) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .addQueryParameter("uid", userId); parameters.forEach(urlBuilder::addQueryParameter); Request request = new Request.Builder().post(emptyBody).url(urlBuilder.build()).build(); String resp = safeCall(request); return gson.fromJson(resp, User.class); } @Override public void suspendUser(String userId, boolean suspend) { modifyUser(userId, ImmutableMap.of("suspended", Boolean.toString(suspend))); } /* * The operation is success if the user is not exist in the system after the operation is * executed. The operation does not throw exception even if the user is not exist in the * beginning. */ @Override public void removeUser(String userId) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .addQueryParameter("uid", userId) .addQueryParameter("purge-data", "true"); Request request = new Request.Builder().delete().url(urlBuilder.build()).build(); safeCall(request); } @Override public Optional getUserQuota(String userId) { return getQuota(userId, "user"); } @Override public Optional getBucketQuota(String userId) { return getQuota(userId, "bucket"); } public Optional getQuota(String userId, String quotaType) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("quota") .addQueryParameter("uid", userId) .addQueryParameter("quota-type", quotaType); Request request = new Request.Builder().get().url(urlBuilder.build()).build(); String resp = safeCall(request); // Fit luminous behavior if (resp == null) { throw new RgwAdminException(404, "NoSuchUser"); } return Optional.ofNullable(gson.fromJson(resp, Quota.class)); } @Override public void setBucketQuota(String userId, long maxObjects, long maxSizeKB) { setQuota(userId, "bucket", maxObjects, maxSizeKB); } @Override public void setUserQuota(String userId, long maxObjects, long maxSizeKB) { setQuota(userId, "user", maxObjects, maxSizeKB); } public void setQuota(String userId, String quotaType, long maxObjects, long maxSizeKB) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("user") .query("quota") .addQueryParameter("uid", userId) .addQueryParameter("quota-type", quotaType); String body = gson.toJson( ImmutableMap.of( "max_objects", String.valueOf(maxObjects), "max_size_kb", String.valueOf(maxSizeKB), "enabled", "true")); Request request = new Request.Builder().put(RequestBody.create(null, body)).url(urlBuilder.build()).build(); safeCall(request); } @Override public void removeObject(String bucketName, String objectKey) { HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .query("object") .addQueryParameter("bucket", bucketName) .addQueryParameter("object", objectKey); Request request = new Request.Builder().delete().url(urlBuilder.build()).build(); safeCall(request); } @Override public Optional getObjectPolicy(String bucketName, String objectKey) { return _getPolicy(bucketName, objectKey); } @Override public Optional getBucketPolicy(String bucketName) { return _getPolicy(bucketName, null); } private Optional _getPolicy(String bucketName, String objectKey) { if (Strings.isNullOrEmpty(bucketName)) { throw new IllegalArgumentException("no bucketName"); } HttpUrl.Builder urlBuilder = HttpUrl.parse(endpoint) .newBuilder() .addPathSegment("bucket") .query("policy") .addQueryParameter("bucket", bucketName); if (!Strings.isNullOrEmpty(objectKey)) { urlBuilder.addQueryParameter("object", objectKey); } Request request = new Request.Builder().get().url(urlBuilder.build()).build(); return Optional.ofNullable(safeCall(request)); } enum MetadataType { USER("user"), BUCKET("bucket"), BUCKET_INSTANCE("bucket.instance"); String s; MetadataType(String s) { this.s = s; } @Override public String toString() { return s; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy