ソースを参照

activation working from frontend

tags/v0.1.6
Jonathan Cobb 5年前
コミット
8638074a5d
12個のファイルの変更64行の追加39行の削除
  1. +2
    -0
      bin/prep_bubble_jar
  2. +1
    -1
      bin/reset_bubble_db
  3. +2
    -0
      bubble-server/src/main/java/bubble/ApiConstants.java
  4. +32
    -9
      bubble-server/src/main/java/bubble/cloud/storage/local/LocalStorageDriver.java
  5. +2
    -0
      bubble-server/src/main/java/bubble/model/cloud/BubbleDomain.java
  6. +2
    -3
      bubble-server/src/main/java/bubble/model/cloud/BubbleFootprint.java
  7. +5
    -0
      bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java
  8. +3
    -0
      bubble-server/src/main/java/bubble/resources/account/AuthResource.java
  9. +9
    -23
      bubble-server/src/main/java/bubble/service/boot/ActivationService.java
  10. +1
    -1
      bubble-server/src/main/java/bubble/service/cloud/StandardStorageService.java
  11. +4
    -1
      bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties
  12. +1
    -1
      bubble-web

+ 2
- 0
bin/prep_bubble_jar ファイルの表示

@@ -84,6 +84,8 @@ echo "------------------------------------------------------------"
cat "${UPDATED}"
echo "------------------------------------------------------------"

cd ${LOCALSTORAGE_BASE_DIR} && jar uvf ${BUBBLE_JAR} automation || die "Error updating ${BUBBLE_JAR} with default role archives"

mkdir -p ${CLASSES_DIR}/scripts
for script in run.sh bubble_common bubble bget bgetn bgeti bpost bposte bput bpute bdelete bscript bmodel bencrypt bdecrypt list_bubble_databases cleanup_bubble_databases ; do
cp ${SCRIPT_DIR}/${script} ${CLASSES_DIR}/scripts || die "Error copying ${SCRIPT_DIR}/${script} -> ${CLASSES_DIR}/scripts"


+ 1
- 1
bin/reset_bubble_db ファイルの表示

@@ -43,5 +43,5 @@ else
fi

dropdb bubble ; createdb bubble && cat ${SQL_DIR}/bubble.sql | psql bubble
echo "Successfully initialized DB schema from:"
echo "Successfully initialized DB schema from: "
echo ${SQL_DIR}/bubble.sql

+ 2
- 0
bubble-server/src/main/java/bubble/ApiConstants.java ファイルの表示

@@ -33,6 +33,8 @@ public class ApiConstants {

public static final int MAX_SEARCH_PAGE = 50;

public static final String ROOT_NETWORK_UUID = "00000000-0000-0000-0000-000000000000";

@Getter(lazy=true) private static final String bubbleDefaultDomain = initDefaultDomain();
private static String initDefaultDomain() {
final File f = new File(HOME_DIR, ".BUBBLE_DEFAULT_DOMAIN");


+ 32
- 9
bubble-server/src/main/java/bubble/cloud/storage/local/LocalStorageDriver.java ファイルの表示

@@ -2,6 +2,7 @@ package bubble.cloud.storage.local;

import bubble.cloud.CloudServiceDriverBase;
import bubble.cloud.storage.StorageServiceDriver;
import bubble.dao.account.AccountDAO;
import bubble.dao.cloud.BubbleNodeDAO;
import bubble.model.cloud.BubbleNetwork;
import bubble.model.cloud.BubbleNode;
@@ -12,7 +13,6 @@ import lombok.Cleanup;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.cobbzilla.util.io.FileUtil;
import org.cobbzilla.wizard.cache.redis.RedisService;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.*;
@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static bubble.ApiConstants.ROOT_NETWORK_UUID;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.notSupported;
import static org.cobbzilla.util.io.FileUtil.*;
@@ -32,7 +33,7 @@ public class LocalStorageDriver extends CloudServiceDriverBase<LocalStorageConfi
public static final String SUFFIX_META = "._bubble_metadata";

@Autowired private BubbleNodeDAO nodeDAO;
@Autowired private RedisService redis;
@Autowired private AccountDAO accountDAO;

public static final String LOCAL_STORAGE = "LocalStorage";
public static final String LOCAL_STORAGE_STANDARD_BASE_DIR = "/home/bubble/.bubble_local_storage";
@@ -43,9 +44,14 @@ public class LocalStorageDriver extends CloudServiceDriverBase<LocalStorageConfi

@Override public boolean _exists(String fromNode, String key) throws IOException {
final BubbleNode from = getFromNode(fromNode);
final File file = keyFile(from, key);
final boolean exists = file.exists();
return exists;
if (from != null) {
final File file = keyFile(from, key);
return file.exists();
}
if (activated()) return false;
// check classpath only if bubble has not been activated
@Cleanup final InputStream in = getClass().getClassLoader().getResourceAsStream(key);
return in != null;
}

protected File metaFile(File f) { return new File(abs(f)+SUFFIX_META); }
@@ -61,9 +67,26 @@ public class LocalStorageDriver extends CloudServiceDriverBase<LocalStorageConfi

@Override public InputStream _read(String fromNode, String key) throws IOException {
final BubbleNode from = getFromNode(fromNode);
final File f = keyFile(from, key);
if (!f.exists()) return null;
return new FileInputStream(f);
if (from != null) {
final File f = keyFile(from, key);
return f.exists() ? new FileInputStream(f) : null;
}

// only try classpath is bubble has not been activated
if (activated()) return null;

@Cleanup InputStream in = getClass().getClassLoader().getResourceAsStream(key);
if (in == null) return null;

// copy file to root network storage, so we can find it after activation
final File file = keyFileForNetwork(ROOT_NETWORK_UUID, config.getBaseDir(), key);
@Cleanup OutputStream out = new FileOutputStream(file);
IOUtils.copyLarge(in, out);
return new FileInputStream(file);
}

public boolean activated() {
return accountDAO.activated() && configuration.getThisNode() != null;
}

@Override public boolean _write(String fromNode, String key, InputStream data, StorageMetadata metadata, String requestId) throws IOException {
@@ -131,7 +154,7 @@ public class LocalStorageDriver extends CloudServiceDriverBase<LocalStorageConfi

protected BubbleNode getFromNode(String fromNode) {
final BubbleNode node = nodeDAO.findByUuid(fromNode);
return node != null ? node : die("fromNode not found: "+fromNode);
return node != null ? node : !activated() ? null : die("fromNode not found: "+fromNode);
}

private File keyFile(BubbleNode from, String key) { return keyFile(from, config.getBaseDir(), key); }


+ 2
- 0
bubble-server/src/main/java/bubble/model/cloud/BubbleDomain.java ファイルの表示

@@ -26,6 +26,7 @@ import java.util.stream.Collectors;
import static bubble.ApiConstants.EP_DOMAINS;
import static bubble.model.cloud.AnsibleRole.sameRoleName;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.dns.DnsType.NS;
import static org.cobbzilla.util.dns.DnsType.SOA;
import static org.cobbzilla.util.json.JsonUtil.json;
@@ -101,6 +102,7 @@ public class BubbleDomain extends IdentifiableBase implements AccountTemplate {

@Type(type=ENCRYPTED_STRING) @Column(columnDefinition="varchar("+(10000+ENC_PAD)+") NOT NULL")
@JsonIgnore @Getter @Setter private String rolesJson;
public boolean hasRoles () { return !empty(getRoles()); }

@Transient public String[] getRoles () { return rolesJson == null ? null : json(rolesJson, String[].class); }
public BubbleDomain setRoles (String[] roles) { return setRolesJson(roles == null ? null : json(roles)); }


+ 2
- 3
bubble-server/src/main/java/bubble/model/cloud/BubbleFootprint.java ファイルの表示

@@ -50,9 +50,8 @@ public class BubbleFootprint extends IdentifiableBase implements AccountTemplate

public static final BubbleFootprint DEFAULT_FOOTPRINT_OBJECT = new BubbleFootprint()
.setName(DEFAULT_FOOTPRINT)
.setDescription("Exclude countries subject to United States OFAC sanctions")
.setTemplate(true)
.setDisallowedCountries(new String[] {"IR", "KP", "SY", "SD", "CU", "VE"});
.setDescription("No restrictions, run anywhere")
.setTemplate(true);

@SuppressWarnings("unused")
public BubbleFootprint (BubbleFootprint other) { copy(this, other, CREATE_FIELDS); }


+ 5
- 0
bubble-server/src/main/java/bubble/model/cloud/BubbleNetwork.java ファイルの表示

@@ -25,6 +25,7 @@ import java.util.Collection;
import java.util.List;

import static bubble.ApiConstants.EP_NETWORKS;
import static bubble.ApiConstants.ROOT_NETWORK_UUID;
import static bubble.model.cloud.BubbleDomain.DOMAIN_NAME_MAXLEN;
import static bubble.model.cloud.BubbleNetworkState.created;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
@@ -55,6 +56,10 @@ public class BubbleNetwork extends IdentifiableBase implements HasNetwork, HasBu

@Override public Identifiable update(Identifiable other) { copy(this, other, UPDATE_FIELDS); return this; }

@Override public void beforeCreate() {
if (!hasUuid() && !getUuid().equals(ROOT_NETWORK_UUID)) super.beforeCreate();
}

@Transient @JsonIgnore public String getNetwork () { return getUuid(); }

@ECSearchable


+ 3
- 0
bubble-server/src/main/java/bubble/resources/account/AuthResource.java ファイルの表示

@@ -28,6 +28,7 @@ import org.glassfish.grizzly.http.server.Request;
import org.glassfish.jersey.server.ContainerRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.Valid;
import javax.ws.rs.*;
@@ -77,10 +78,12 @@ public class AuthResource {
@GET @Path(EP_ACTIVATE)
public Response isActivated(@Context ContainerRequest ctx) { return ok(accountDAO.activated()); }

@Transactional
@PUT @Path(EP_ACTIVATE)
public Response activate(@Context Request req,
@Context ContainerRequest ctx,
@Valid ActivationRequest request) {
if (request == null) return invalid("err.activationRequest.required");
final Account found = optionalUserPrincipal(ctx);
if (found != null) {
if (!found.admin()) return forbidden();


+ 9
- 23
bubble-server/src/main/java/bubble/service/boot/ActivationService.java ファイルの表示

@@ -1,5 +1,6 @@
package bubble.service.boot;

import bubble.ApiConstants;
import bubble.cloud.CloudServiceType;
import bubble.cloud.compute.ComputeNodeSizeType;
import bubble.cloud.compute.local.LocalComputeDriver;
@@ -11,13 +12,11 @@ import bubble.model.account.ActivationRequest;
import bubble.model.cloud.*;
import bubble.server.BubbleConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.cobbzilla.wizard.model.IdentifiableBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;

import static bubble.cloud.storage.StorageServiceDriver.STORAGE_PREFIX;
import static bubble.cloud.storage.local.LocalStorageDriver.LOCAL_STORAGE;
@@ -26,7 +25,6 @@ import static bubble.model.cloud.BubbleFootprint.DEFAULT_FOOTPRINT_OBJECT;
import static bubble.model.cloud.BubbleNetwork.TAG_ALLOW_REGISTRATION;
import static bubble.model.cloud.BubbleNetwork.TAG_PARENT_ACCOUNT;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.cobbzilla.util.daemon.ZillaRuntime.background;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.io.FileUtil.toStringOrDie;
import static org.cobbzilla.util.io.StreamUtil.stream2string;
@@ -40,7 +38,6 @@ public class ActivationService {

public static final String DEFAULT_ROLES = "ansible/default_roles.json";

public static final String ROOT_NETWORK_UUID = "00000000-0000-0000-0000-000000000000";
public static final long ROOT_CREATE_TIMEOUT = SECONDS.toMillis(10);

@Autowired private AnsibleRoleDAO roleDAO;
@@ -82,9 +79,15 @@ public class ActivationService {
.setAccount(account.getUuid()));
}

final AnsibleRole[] roles = request.hasRoles() ? request.getRoles() : json(loadDefaultRoles(), AnsibleRole[].class);
for (AnsibleRole role : roles) {
roleDAO.create(role.setAccount(account.getUuid()));
}

final BubbleDomain domain = domainDAO.create(new BubbleDomain(request.getDomain())
.setAccount(account.getUuid())
.setPublicDns(publicDns.getUuid())
.setRoles(Arrays.stream(roles).map(AnsibleRole::getName).toArray(String[]::new))
.setTemplate(true));

BubbleFootprint footprint = footprintDAO.findByAccountAndId(account.getUuid(), DEFAULT_FOOTPRINT);
@@ -133,10 +136,6 @@ public class ActivationService {

selfNodeService.setActivated(node);

final AnsibleRole[] roles = request.hasRoles() ? request.getRoles() : json(loadDefaultRoles(), AnsibleRole[].class);
for (AnsibleRole role : roles) {
roleDAO.create(role.setAccount(account.getUuid()));
}
String[] domainRoles = request.getDomain().getRoles();
if (domainRoles == null || domainRoles.length == 0) {
domainRoles = Arrays.stream(roles).map(AnsibleRole::getName).toArray(String[]::new);
@@ -161,21 +160,8 @@ public class ActivationService {
}

public BubbleNetwork createRootNetwork(BubbleNetwork network) {
network.setUuid(ROOT_NETWORK_UUID);
final AtomicReference<Object> ref = new AtomicReference<>();
try {
background(() -> {
IdentifiableBase.getEnforceNullUuidOnCreate().set(false);
ref.set(networkDAO.create(network));
},
ref::set).join(ROOT_CREATE_TIMEOUT);
} catch (InterruptedException e) {
return die("createRoot: interrupted: "+e);
}
final Object o = ref.get();
if (o instanceof BubbleNetwork) return (BubbleNetwork) o;
if (o instanceof Exception) return die((Exception) o);
return die("createRoot: ref was unset");
network.setUuid(ApiConstants.ROOT_NETWORK_UUID);
return networkDAO.create(network);
}

}

+ 1
- 1
bubble-server/src/main/java/bubble/service/cloud/StandardStorageService.java ファイルの表示

@@ -40,7 +40,7 @@ public class StandardStorageService implements StorageService {
}
}

private String thisNodeId() { return configuration.getThisNode().getUuid(); }
private String thisNodeId() { return configuration.getThisNode() != null ? configuration.getThisNode().getUuid() : null; }

public boolean exists(String account, String uri) {
final StorageTarget target = new StorageTarget(account, uri);


+ 4
- 1
bubble-server/src/main/resources/message_templates/en_US/server/pre_auth/ResourceMessages.properties ファイルの表示

@@ -8,6 +8,7 @@ message_false=False
message_null=null
message_undefined=undefined

err.activationRequest.required=Activation request object is required
err.name.required=Name is required
err.name.tooShort=Name must be at least 4 characters
err.name.tooLong=Name cannot be longer than 100 characters
@@ -37,6 +38,8 @@ err.accountInit.timeout=Timeout initializing new account
# Activation form
form_title_activation=Activate Bubble
field_label_description=Description
field_label_domain=Domain Name
field_label_domain_description=Enter a domain that is managed by this DNS service. Bubbles will be launched within this domain.
field_label_network_name=Network Name
field_label_dns_service=DNS Service
field_label_storage_service=Storage Service
@@ -167,7 +170,7 @@ driver_credential_AWS_SECRET_KEY_bubble.cloud.storage.s3.S3StorageDriver=AWS Sec
driver_config_region_bubble.cloud.storage.s3.S3StorageDriver=AWS Region
driver_config_description_region_bubble.cloud.storage.s3.S3StorageDriver=The AWS Region to use. Must be a valid name in the AWS <a href="https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-core/src/main/java/com/amazonaws/regions/Regions.java">Regions</a> enum class.
driver_config_bucket_bubble.cloud.storage.s3.S3StorageDriver=S3 Bucket Name
driver_config_description_bucket_bubble.cloud.storage.s3.S3StorageDriver=The name of the S3 bucket to use. The credentials provided in AWS Access Key and AWS Secret key must have permissions to read, write, and list objects in this bucket.
driver_config_description_bucket_bubble.cloud.storage.s3.S3StorageDriver=The name of the S3 bucket to use. The credentials provided in AWS Access Key and AWS Secret key must have permissions to read, write, and list objects in this bucket. If the bucket does not exist, it will be created -- in this case the credentials must also have permissions to create new buckets.
driver_config_prefix_bubble.cloud.storage.s3.S3StorageDriver=S3 Bucket Prefix
driver_config_description_prefix_bubble.cloud.storage.s3.S3StorageDriver=The bucket prefix (subdirectory) to use. All objects stored in S3 will be put under this prefix. This allows you to use the same S3 Bucket for multiple Bubbles, as long as they each use a distinct prefix.
driver_config_listFetchSize_bubble.cloud.storage.s3.S3StorageDriver=S3 List Fetch Size


+ 1
- 1
bubble-web

@@ -1 +1 @@
Subproject commit 6c141907a646db2d5357bff3607391a23407de8c
Subproject commit 3eab904291f158ab130c549a2bdd15bb77f0ec03

読み込み中…
キャンセル
保存