@Override public Distribution read(String origin, Distribution.Method method) { if (method.equals(Distribution.DOWNLOAD) || method.equals(Distribution.STREAMING) || method.equals(Distribution.CUSTOM) || method.equals(Distribution.WEBSITE_CDN)) { if (!distributionStatus.get(method).containsKey(origin)) { try { this.check(); this.message( MessageFormat.format( Locale.localizedString("Reading CDN configuration of {0}", "Status"), origin)); this.cache(origin, method); } catch (CloudFrontServiceException e) { this.error("Cannot read CDN configuration", e); } catch (LoginCanceledException canceled) { // User canceled Cloudfront login. Possibly not enabled in Amazon configuration. distributionStatus .get(method) .put( origin, new Distribution(null, origin, method, false, null, canceled.getMessage())); } catch (IOException e) { this.error("Cannot read CDN configuration", e); } } } if (distributionStatus.get(method).containsKey(origin)) { return distributionStatus.get(method).get(origin); } return new Distribution(origin, method); }
/** * Amazon CloudFront Extension used to list all configured distributions * * @param origin Name of the container * @param method Distribution method * @throws CloudFrontServiceException CloudFront failure details * @throws IOException Service error */ private void cache(String origin, Distribution.Method method) throws IOException, CloudFrontServiceException { if (log.isDebugEnabled()) { log.debug(String.format("List distributions for origin %s", origin)); } CloudFrontService cf = this.getClient(); if (method.equals(Distribution.STREAMING)) { for (org.jets3t.service.model.cloudfront.Distribution d : cf.listStreamingDistributions(origin)) { for (Origin o : d.getConfig().getOrigins()) { if (o instanceof S3Origin) { // Write to cache distributionStatus.get(method).put(origin, this.convert(d, method)); // We currently only support one distribution per bucket break; } } } } else if (method.equals(Distribution.DOWNLOAD)) { // List distributions restricting to bucket name origin for (org.jets3t.service.model.cloudfront.Distribution d : cf.listDistributions(origin)) { for (Origin o : d.getConfig().getOrigins()) { if (o instanceof S3Origin) { // Write to cache distributionStatus.get(method).put(origin, this.convert(d, method)); // We currently only support one distribution per bucket break; } } } } else if (method.equals(Distribution.CUSTOM) || method.equals(Distribution.WEBSITE_CDN)) { for (org.jets3t.service.model.cloudfront.Distribution d : cf.listDistributions()) { for (Origin o : d.getConfig().getOrigins()) { // Listing all distributions and look for custom origin if (o instanceof CustomOrigin) { if (o.getDomainName().equals(origin)) { distributionStatus.get(method).put(origin, this.convert(d, method)); } } } } } }
private Distribution convert( final org.jets3t.service.model.cloudfront.Distribution d, Distribution.Method method) throws IOException, CloudFrontServiceException { // Retrieve distributions configuration to access current logging status settings. final DistributionConfig distributionConfig = this.getDistributionConfig(d); final String loggingTarget; if (null == distributionConfig.getLoggingStatus()) { // Default logging target to origin itself loggingTarget = ServiceUtils.findBucketNameInHostname( d.getConfig().getOrigin().getDomainName(), Protocol.S3_SSL.getDefaultHostname()); } else { loggingTarget = ServiceUtils.findBucketNameInHostname( distributionConfig.getLoggingStatus().getBucket(), Protocol.S3_SSL.getDefaultHostname()); } final Distribution distribution = new Distribution( d.getId(), distributionConfig.getEtag(), distributionConfig.getCallerReference(), d.getConfig().getOrigin().getDomainName(), method, d.getConfig().isEnabled(), d.isDeployed(), // CloudFront URL String.format("%s://%s%s", method.getScheme(), d.getDomainName(), method.getContext()), method.equals(Distribution.DOWNLOAD) || method.equals(Distribution.CUSTOM) ? String.format("https://%s%s", d.getDomainName(), method.getContext()) : null, // No SSL null, Locale.localizedString(d.getStatus(), "S3"), distributionConfig.getCNAMEs(), distributionConfig.getLoggingStatus().isEnabled(), loggingTarget, distributionConfig.getDefaultRootObject()); if (this.isInvalidationSupported(method)) { distribution.setInvalidationStatus(this.readInvalidationStatus(distribution)); } if (this.isLoggingSupported(method)) { distribution.setContainers(this.getContainers()); } return distribution; }
/** * Amazon CloudFront Extension used to enable or disable a distribution configuration and its * CNAMESs * * @param enabled Distribution status * @param method Distribution method * @param origin Name of the container * @param distributionId Distribution reference * @param cnames DNS CNAME aliases for distribution * @param logging Access log configuration * @param defaultRootObject Index file for distribution. Only supported for download and custom * origins. * @throws CloudFrontServiceException CloudFront failure details * @throws IOException I/O error */ private void updateDistribution( boolean enabled, Distribution.Method method, final String origin, final String distributionId, final String etag, final String reference, final String[] cnames, final LoggingStatus logging, final String defaultRootObject) throws CloudFrontServiceException, IOException { if (log.isDebugEnabled()) { log.debug(String.format("Update %s distribution with origin %s", method.toString(), origin)); } final String originId = UUID.randomUUID().toString(); final CacheBehavior cacheBehavior = new CacheBehavior(originId, false, null, CacheBehavior.ViewerProtocolPolicy.ALLOW_ALL, 0L); final CloudFrontService cf = this.getClient(); if (method.equals(Distribution.STREAMING)) { StreamingDistributionConfig config = new StreamingDistributionConfig( new Origin[] {new S3Origin(originId, origin, null)}, reference, cnames, null, enabled, logging, null); config.setEtag(etag); cf.updateDistributionConfig(distributionId, config); } else if (method.equals(Distribution.DOWNLOAD)) { DistributionConfig config = new DistributionConfig( new Origin[] {new S3Origin(originId, origin, null)}, reference, cnames, null, enabled, logging, defaultRootObject, cacheBehavior, new CacheBehavior[] {}); config.setEtag(etag); cf.updateDistributionConfig(distributionId, config); } else if (method.equals(Distribution.CUSTOM) || method.equals(Distribution.WEBSITE_CDN)) { DistributionConfig config = new DistributionConfig( new Origin[] {this.getCustomOriginConfiguration(originId, method, origin)}, reference, cnames, null, enabled, logging, defaultRootObject, cacheBehavior, new CacheBehavior[] {}); config.setEtag(etag); cf.updateDistributionConfig(distributionId, config); } else { throw new RuntimeException("Invalid distribution method:" + method); } }
/** * Amazon CloudFront Extension to create a new distribution configuration * * * @param enabled Distribution status * @param method Distribution method * @param origin Name of the container * @param cnames DNS CNAME aliases for distribution * @param logging Access log configuration * @param defaultRootObject Index file for distribution. Only supported for download and custom * origins. * @return Distribution configuration * @throws CloudFrontServiceException CloudFront failure details * @throws ConnectionCanceledException Authentication canceled */ private org.jets3t.service.model.cloudfront.Distribution createDistribution( boolean enabled, Distribution.Method method, final String origin, String[] cnames, LoggingStatus logging, String defaultRootObject) throws ConnectionCanceledException, CloudFrontServiceException { final String reference = String.valueOf(System.currentTimeMillis()); if (log.isDebugEnabled()) { log.debug(String.format("Create new %s distribution", method.toString())); } CloudFrontService cf = this.getClient(); final String originId = UUID.randomUUID().toString(); final CacheBehavior cacheBehavior = new CacheBehavior(originId, false, null, CacheBehavior.ViewerProtocolPolicy.ALLOW_ALL, 0L); if (method.equals(Distribution.STREAMING)) { final StreamingDistributionConfig config = new StreamingDistributionConfig( new S3Origin[] {new S3Origin(originId, origin, null)}, reference, cnames, null, enabled, logging, null); return cf.createDistribution(config); } if (method.equals(Distribution.DOWNLOAD)) { DistributionConfig config = new DistributionConfig( new Origin[] {new S3Origin(originId, origin, null)}, reference, cnames, null, enabled, logging, defaultRootObject, cacheBehavior, new CacheBehavior[] {}); return cf.createDistribution(config); } if (method.equals(Distribution.CUSTOM) || method.equals(Distribution.WEBSITE_CDN)) { DistributionConfig config = new DistributionConfig( new Origin[] { new CustomOrigin(originId, origin, CustomOrigin.OriginProtocolPolicy.MATCH_VIEWER) }, reference, cnames, null, enabled, logging, defaultRootObject, cacheBehavior, new CacheBehavior[] {}); return cf.createDistribution(config); } throw new RuntimeException("Invalid distribution method:" + method); }
@Override public boolean isLoggingSupported(Distribution.Method method) { return method.equals(Distribution.DOWNLOAD) || method.equals(Distribution.STREAMING) || method.equals(Distribution.CUSTOM); }
@Override public boolean isInvalidationSupported(Distribution.Method method) { return method.equals(Distribution.DOWNLOAD) || method.equals(Distribution.WEBSITE_CDN) || method.equals(Distribution.CUSTOM); }
@Override public void write( boolean enabled, String origin, Distribution.Method method, String[] cnames, boolean logging, String loggingBucket, String defaultRootObject) { try { this.check(); // Configure CDN LoggingStatus loggingStatus = null; if (logging) { if (this.isLoggingSupported(method)) { final String loggingDestination = StringUtils.isNotBlank(loggingBucket) ? ServiceUtils.generateS3HostnameForBucket( loggingBucket, false, Protocol.S3_SSL.getDefaultHostname()) : origin; loggingStatus = new LoggingStatus( loggingDestination, Preferences.instance().getProperty("cloudfront.logging.prefix")); } } StringBuilder name = new StringBuilder(Locale.localizedString("Amazon CloudFront", "S3")) .append(" ") .append(method.toString()); if (enabled) { this.message( MessageFormat.format( Locale.localizedString("Enable {0} Distribution", "Status"), name)); } else { this.message( MessageFormat.format( Locale.localizedString("Disable {0} Distribution", "Status"), name)); } Distribution d = distributionStatus.get(method).get(origin); if (null == d) { if (log.isDebugEnabled()) { log.debug(String.format("No existing distribution found for method %s", method)); } this.createDistribution(enabled, method, origin, cnames, loggingStatus, defaultRootObject); } else { boolean modified = false; if (d.isEnabled() != enabled) { modified = true; } if (!Arrays.equals(d.getCNAMEs(), cnames)) { modified = true; } if (d.isLogging() != logging) { modified = true; } // Compare default root object for possible change if (!StringUtils.equals(d.getDefaultRootObject(), defaultRootObject)) { modified = true; } // Compare logging target for possible change if (!StringUtils.equals(d.getLoggingTarget(), loggingBucket)) { modified = true; } if (modified) { this.updateDistribution( enabled, method, origin, d.getId(), d.getEtag(), d.getReference(), cnames, loggingStatus, defaultRootObject); } else { log.info("Skip updating distribution not modified."); } } } catch (CloudFrontServiceException e) { this.error("Cannot write CDN configuration", e); } catch (IOException e) { this.error("Cannot write CDN configuration", e); } finally { distributionStatus.get(method).clear(); } }