http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Environment.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Environment.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Environment.java new file mode 100644 index 0000000..48e6efa --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Environment.java @@ -0,0 +1,178 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.util.Map; + +import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * An environment. + */ +public class Environment { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private ImmutableMap.Builder<String, JsonBall> attributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder(); + private String description = ""; + private ImmutableMap.Builder<String, String> cookbookVersions = ImmutableMap.builder(); + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder attribute(String key, JsonBall value) { + this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder attributes(Map<String, JsonBall> attributes) { + this.attributes.putAll(checkNotNull(attributes, "attributes")); + return this; + } + + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } + + public Builder cookbookVersion(String key, String version) { + this.cookbookVersions.put(checkNotNull(key, "key"), checkNotNull(version, "version")); + return this; + } + + public Builder cookbookVersions(Map<String, String> cookbookVersions) { + this.cookbookVersions.putAll(checkNotNull(cookbookVersions, "cookbookVersions")); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Environment build() { + return new Environment(name, attributes.build(), overrideAttributes.build(), description, + cookbookVersions.build()); + } + } + + private final String name; + @SerializedName("default_attributes") + private final Map<String, JsonBall> attributes; + @SerializedName("override_attributes") + private final Map<String, JsonBall> overrideAttributes; + private final String description; + @SerializedName("cookbook_versions") + private final Map<String, String> cookbookVersions; + + // internal + @SerializedName("json_class") + private final String _jsonClass = "Chef::Environment"; + @SerializedName("chef_type") + private final String _chefType = "environment"; + + @ConstructorProperties({ "name", "default_attributes", "override_attributes", "description", "cookbook_versions" }) + protected Environment(String name, @Nullable Map<String, JsonBall> attributes, + @Nullable Map<String, JsonBall> overrideAttributes, String description, + @Nullable Map<String, String> cookbookVersions) { + this.name = name; + this.attributes = copyOfOrEmpty(attributes); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); + this.description = description; + this.cookbookVersions = copyOfOrEmpty(cookbookVersions); + } + + public String getName() { + return name; + } + + public Map<String, JsonBall> getAttributes() { + return attributes; + } + + public Map<String, JsonBall> getOverrideAttributes() { + return overrideAttributes; + } + + public String getDescription() { + return description; + } + + public Map<String, String> getCookbookVersions() { + return cookbookVersions; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Environment that = (Environment) o; + + if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) + return false; + if (cookbookVersions != null ? !cookbookVersions.equals(that.cookbookVersions) : that.cookbookVersions != null) + return false; + if (description != null ? !description.equals(that.description) : that.description != null) + return false; + if (!name.equals(that.name)) + return false; + if (overrideAttributes != null ? !overrideAttributes.equals(that.overrideAttributes) + : that.overrideAttributes != null) + return false; + + return true; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + (attributes != null ? attributes.hashCode() : 0); + result = 31 * result + (overrideAttributes != null ? overrideAttributes.hashCode() : 0); + result = 31 * result + (description != null ? description.hashCode() : 0); + result = 31 * result + (cookbookVersions != null ? cookbookVersions.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Environment [" + "name='" + name + '\'' + ", attributes=" + attributes + ", overrideAttributes=" + + overrideAttributes + ", description='" + description + '\'' + ", cookbookVersions=" + cookbookVersions + + ']'; + } +}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Metadata.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Metadata.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Metadata.java new file mode 100644 index 0000000..33f8dfb --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Metadata.java @@ -0,0 +1,447 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.util.Map; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * A metadata object. + */ +public class Metadata { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String license; + private String maintainer; + private ImmutableMap.Builder<String, String> suggestions = ImmutableMap.builder(); + private ImmutableMap.Builder<String, String> dependencies = ImmutableMap.builder(); + private String maintainerEmail; + private ImmutableMap.Builder<String, String> conflicting = ImmutableMap.builder(); + private String description; + private ImmutableMap.Builder<String, String> providing = ImmutableMap.builder(); + private ImmutableMap.Builder<String, String> platforms = ImmutableMap.builder(); + private String version; + private ImmutableMap.Builder<String, String> recipes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, String> replacing = ImmutableMap.builder(); + private String name; + private ImmutableMap.Builder<String, String> groupings = ImmutableMap.builder(); + private String longDescription; + private ImmutableMap.Builder<String, Attribute> attributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, String> recommendations = ImmutableMap.builder(); + + public Builder license(String license) { + this.license = checkNotNull(license, "license"); + return this; + } + + public Builder maintainer(String maintainer) { + this.maintainer = checkNotNull(maintainer, "maintainer"); + return this; + } + + public Builder suggestion(String key, String value) { + this.suggestions.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder suggestions(Map<String, String> suggestions) { + this.suggestions.putAll(checkNotNull(suggestions, "suggestions")); + return this; + } + + public Builder dependency(String key, String value) { + this.dependencies.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder dependencies(Map<String, String> dependencies) { + this.dependencies.putAll(checkNotNull(dependencies, "dependencies")); + return this; + } + + public Builder maintainerEmail(String maintainerEmail) { + this.maintainerEmail = checkNotNull(maintainerEmail, "maintainerEmail"); + return this; + } + + public Builder conflicting(String key, String value) { + this.conflicting.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder conflicting(Map<String, String> conflicting) { + this.conflicting.putAll(checkNotNull(conflicting, "conflicting")); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Builder providing(String key, String value) { + this.providing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder providing(Map<String, String> providing) { + this.providing.putAll(checkNotNull(providing, "providing")); + return this; + } + + public Builder platform(String key, String value) { + this.platforms.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder platforms(Map<String, String> platforms) { + this.platforms.putAll(checkNotNull(platforms, "platforms")); + return this; + } + + public Builder version(String version) { + this.version = checkNotNull(version, "version"); + return this; + } + + public Builder recipe(String key, String value) { + this.recipes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder recipes(Map<String, String> recipes) { + this.recipes.putAll(checkNotNull(recipes, "recipes")); + return this; + } + + public Builder replacing(String key, String value) { + this.replacing.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder replacing(Map<String, String> replacing) { + this.replacing.putAll(checkNotNull(replacing, "replacing")); + return this; + } + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder grouping(String key, String value) { + this.groupings.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder grouping(Map<String, String> groupings) { + this.groupings.putAll(checkNotNull(groupings, "groupings")); + return this; + } + + public Builder longDescription(String longDescription) { + this.longDescription = checkNotNull(longDescription, "longDescription"); + return this; + } + + public Builder attribute(String key, Attribute value) { + this.attributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder attributes(Map<String, Attribute> attributes) { + this.attributes.putAll(checkNotNull(attributes, "attributes")); + return this; + } + + public Builder recommendation(String key, String value) { + this.recommendations.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder recommendations(Map<String, String> recommendations) { + this.recommendations.putAll(checkNotNull(recommendations, "recommendations")); + return this; + } + + public Metadata build() { + return new Metadata(license, maintainer, suggestions.build(), dependencies.build(), maintainerEmail, + conflicting.build(), description, providing.build(), platforms.build(), version, recipes.build(), + replacing.build(), name, groupings.build(), longDescription, attributes.build(), recommendations.build()); + } + + } + + private final String license; + private final String maintainer; + private final Map<String, String> suggestions; + private final Map<String, String> dependencies; + @SerializedName("maintainer_email") + private final String maintainerEmail; + private final Map<String, String> conflicting; + private final String description; + private final Map<String, String> providing; + private final Map<String, String> platforms; + private final String version; + private final Map<String, String> recipes; + private final Map<String, String> replacing; + private final String name; + private final Map<String, String> groupings; + @SerializedName("long_description") + private final String longDescription; + private final Map<String, Attribute> attributes; + private final Map<String, String> recommendations; + + @ConstructorProperties({ "license", "maintainer", "suggestions", "dependencies", "maintainer_email", "conflicting", + "description", "providing", "platforms", "version", "recipes", "replacing", "name", "groupings", + "long_description", "attributes", "recommendations" }) + protected Metadata(String license, String maintainer, @Nullable Map<String, String> suggestions, + @Nullable Map<String, String> dependencies, String maintainerEmail, @Nullable Map<String, String> conflicting, + String description, @Nullable Map<String, String> providing, @Nullable Map<String, String> platforms, + String version, @Nullable Map<String, String> recipes, @Nullable Map<String, String> replacing, String name, + @Nullable Map<String, String> groupings, String longDescription, @Nullable Map<String, Attribute> attributes, + @Nullable Map<String, String> recommendations) { + this.license = license; + this.maintainer = maintainer; + this.suggestions = copyOfOrEmpty(suggestions); + this.dependencies = copyOfOrEmpty(dependencies); + this.maintainerEmail = maintainerEmail; + this.conflicting = copyOfOrEmpty(conflicting); + this.description = description; + this.providing = copyOfOrEmpty(providing); + this.platforms = copyOfOrEmpty(platforms); + this.version = version; + this.recipes = copyOfOrEmpty(recipes); + this.replacing = copyOfOrEmpty(replacing); + this.name = name; + this.groupings = copyOfOrEmpty(groupings); + this.longDescription = longDescription; + this.attributes = copyOfOrEmpty(attributes); + this.recommendations = copyOfOrEmpty(recommendations); + } + + public String getLicense() { + return license; + } + + public String getMaintainer() { + return maintainer; + } + + public Map<String, String> getSuggestions() { + return suggestions; + } + + public Map<String, String> getDependencies() { + return dependencies; + } + + public String getMaintainerEmail() { + return maintainerEmail; + } + + public Map<String, String> getConflicting() { + return conflicting; + } + + public String getDescription() { + return description; + } + + public Map<String, String> getProviding() { + return providing; + } + + public Map<String, String> getPlatforms() { + return platforms; + } + + public String getVersion() { + return version; + } + + public Map<String, String> getRecipes() { + return recipes; + } + + public Map<String, String> getReplacing() { + return replacing; + } + + public String getName() { + return name; + } + + public Map<String, String> getGroupings() { + return groupings; + } + + public String getLongDescription() { + return longDescription; + } + + public Map<String, Attribute> getAttributes() { + return attributes; + } + + public Map<String, String> getRecommendations() { + return recommendations; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((attributes == null) ? 0 : attributes.hashCode()); + result = prime * result + ((conflicting == null) ? 0 : conflicting.hashCode()); + result = prime * result + ((dependencies == null) ? 0 : dependencies.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((groupings == null) ? 0 : groupings.hashCode()); + result = prime * result + ((license == null) ? 0 : license.hashCode()); + result = prime * result + ((longDescription == null) ? 0 : longDescription.hashCode()); + result = prime * result + ((maintainer == null) ? 0 : maintainer.hashCode()); + result = prime * result + ((maintainerEmail == null) ? 0 : maintainerEmail.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((platforms == null) ? 0 : platforms.hashCode()); + result = prime * result + ((providing == null) ? 0 : providing.hashCode()); + result = prime * result + ((recipes == null) ? 0 : recipes.hashCode()); + result = prime * result + ((recommendations == null) ? 0 : recommendations.hashCode()); + result = prime * result + ((replacing == null) ? 0 : replacing.hashCode()); + result = prime * result + ((suggestions == null) ? 0 : suggestions.hashCode()); + result = prime * result + ((version == null) ? 0 : version.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Metadata other = (Metadata) obj; + if (attributes == null) { + if (other.attributes != null) + return false; + } else if (!attributes.equals(other.attributes)) + return false; + if (conflicting == null) { + if (other.conflicting != null) + return false; + } else if (!conflicting.equals(other.conflicting)) + return false; + if (dependencies == null) { + if (other.dependencies != null) + return false; + } else if (!dependencies.equals(other.dependencies)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (groupings == null) { + if (other.groupings != null) + return false; + } else if (!groupings.equals(other.groupings)) + return false; + if (license == null) { + if (other.license != null) + return false; + } else if (!license.equals(other.license)) + return false; + if (longDescription == null) { + if (other.longDescription != null) + return false; + } else if (!longDescription.equals(other.longDescription)) + return false; + if (maintainer == null) { + if (other.maintainer != null) + return false; + } else if (!maintainer.equals(other.maintainer)) + return false; + if (maintainerEmail == null) { + if (other.maintainerEmail != null) + return false; + } else if (!maintainerEmail.equals(other.maintainerEmail)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (platforms == null) { + if (other.platforms != null) + return false; + } else if (!platforms.equals(other.platforms)) + return false; + if (providing == null) { + if (other.providing != null) + return false; + } else if (!providing.equals(other.providing)) + return false; + if (recipes == null) { + if (other.recipes != null) + return false; + } else if (!recipes.equals(other.recipes)) + return false; + if (recommendations == null) { + if (other.recommendations != null) + return false; + } else if (!recommendations.equals(other.recommendations)) + return false; + if (replacing == null) { + if (other.replacing != null) + return false; + } else if (!replacing.equals(other.replacing)) + return false; + if (suggestions == null) { + if (other.suggestions != null) + return false; + } else if (!suggestions.equals(other.suggestions)) + return false; + if (version == null) { + if (other.version != null) + return false; + } else if (!version.equals(other.version)) + return false; + return true; + } + + @Override + public String toString() { + return "Metadata [attributes=" + attributes + ", conflicting=" + conflicting + ", dependencies=" + dependencies + + ", description=" + description + ", groupings=" + groupings + ", license=" + license + + ", longDescription=" + longDescription + ", maintainer=" + maintainer + ", maintainerEmail=" + + maintainerEmail + ", name=" + name + ", platforms=" + platforms + ", providing=" + providing + + ", recipes=" + recipes + ", recommendations=" + recommendations + ", replacing=" + replacing + + ", suggestions=" + suggestions + ", version=" + version + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Node.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Node.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Node.java new file mode 100644 index 0000000..ec83f4c --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Node.java @@ -0,0 +1,263 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.util.List; +import java.util.Map; + +import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * Node object. + */ +public class Node { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private ImmutableMap.Builder<String, JsonBall> normalAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, JsonBall> defaultAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, JsonBall> automaticAttributes = ImmutableMap.builder(); + private ImmutableList.Builder<String> runList = ImmutableList.builder(); + private String environment; + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder normalAttribute(String key, JsonBall value) { + this.normalAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder normalAttributes(Map<String, JsonBall> normalAttributes) { + this.normalAttributes.putAll(checkNotNull(normalAttributes, "normalAttributes")); + return this; + } + + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } + + public Builder defaultAttribute(String key, JsonBall value) { + this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder defaultAttributes(Map<String, JsonBall> defaultAttributes) { + this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); + return this; + } + + public Builder automaticAttribute(String key, JsonBall value) { + this.automaticAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder automaticAttributes(Map<String, JsonBall> automaticAttribute) { + this.automaticAttributes.putAll(checkNotNull(automaticAttribute, "automaticAttribute")); + return this; + } + + public Builder runListElement(String element) { + this.runList.add(checkNotNull(element, "element")); + return this; + } + + public Builder runList(Iterable<String> runList) { + this.runList.addAll(checkNotNull(runList, "runList")); + return this; + } + + /** + * @since Chef 0.10 + */ + public Builder environment(String environment) { + this.environment = checkNotNull(environment, "environment"); + return this; + } + + public Node build() { + return new Node(name, normalAttributes.build(), overrideAttributes.build(), defaultAttributes.build(), + automaticAttributes.build(), runList.build(), environment); + } + } + + private final String name; + @SerializedName("normal") + private final Map<String, JsonBall> normalAttributes; + @SerializedName("override") + private final Map<String, JsonBall> overrideAttributes; + @SerializedName("default") + private final Map<String, JsonBall> defaultAttributes; + @SerializedName("automatic") + private final Map<String, JsonBall> automaticAttributes; + @SerializedName("run_list") + private final List<String> runList; + @SerializedName("chef_environment") + private final String environment; + + // internal + @SerializedName("json_class") + private final String _jsonClass = "Chef::Node"; + @SerializedName("chef_type") + private final String _chefType = "node"; + + @ConstructorProperties({ "name", "normal", "override", "default", "automatic", "run_list", "chef_environment" }) + protected Node(String name, @Nullable Map<String, JsonBall> normalAttributes, + @Nullable Map<String, JsonBall> overrideAttributes, @Nullable Map<String, JsonBall> defaultAttributes, + @Nullable Map<String, JsonBall> automaticAttributes, List<String> runList, @Nullable String environment) { + this.name = name; + this.environment = environment; + this.normalAttributes = copyOfOrEmpty(normalAttributes); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); + this.defaultAttributes = copyOfOrEmpty(defaultAttributes); + this.automaticAttributes = copyOfOrEmpty(automaticAttributes); + this.runList = copyOfOrEmpty(runList); + } + + public String getName() { + return name; + } + + public Map<String, JsonBall> getNormalAttributes() { + return normalAttributes; + } + + public Map<String, JsonBall> getOverrideAttributes() { + return overrideAttributes; + } + + public Map<String, JsonBall> getDefaultAttributes() { + return defaultAttributes; + } + + public Map<String, JsonBall> getAutomaticAttributes() { + return automaticAttributes; + } + + public List<String> getRunList() { + return runList; + } + + /** + * @since Chef 0.10 + */ + public String getEnvironment() { + return environment; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); + result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); + result = prime * result + ((automaticAttributes == null) ? 0 : automaticAttributes.hashCode()); + result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((normalAttributes == null) ? 0 : normalAttributes.hashCode()); + result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); + result = prime * result + ((runList == null) ? 0 : runList.hashCode()); + result = prime * result + ((environment == null) ? 0 : environment.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Node other = (Node) obj; + if (_chefType == null) { + if (other._chefType != null) + return false; + } else if (!_chefType.equals(other._chefType)) + return false; + if (_jsonClass == null) { + if (other._jsonClass != null) + return false; + } else if (!_jsonClass.equals(other._jsonClass)) + return false; + if (automaticAttributes == null) { + if (other.automaticAttributes != null) + return false; + } else if (!automaticAttributes.equals(other.automaticAttributes)) + return false; + if (defaultAttributes == null) { + if (other.defaultAttributes != null) + return false; + } else if (!defaultAttributes.equals(other.defaultAttributes)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (normalAttributes == null) { + if (other.normalAttributes != null) + return false; + } else if (!normalAttributes.equals(other.normalAttributes)) + return false; + if (overrideAttributes == null) { + if (other.overrideAttributes != null) + return false; + } else if (!overrideAttributes.equals(other.overrideAttributes)) + return false; + if (runList == null) { + if (other.runList != null) + return false; + } else if (!runList.equals(other.runList)) + return false; + if (environment == null) { + if (other.environment != null) + return false; + } else if (!environment.equals(other.environment)) + return false; + return true; + } + + @Override + public String toString() { + return "Node [name=" + name + ", runList=" + runList + ", normalAttributes=" + normalAttributes + + ", defaultAttributes=" + defaultAttributes + ", overrideAttributes=" + overrideAttributes + + ", chefEnvironment=" + environment + ", automaticAttributes=" + automaticAttributes + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Resource.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Resource.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Resource.java new file mode 100644 index 0000000..94b5471 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Resource.java @@ -0,0 +1,169 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.beans.ConstructorProperties; +import java.net.URI; +import java.util.Arrays; + +import org.jclouds.io.payloads.FilePayload; + +import com.google.common.primitives.Bytes; + +/** + * Resource object. + */ +public class Resource { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private URI url; + private byte[] checksum; + private String path; + private String specificity = "default"; + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder url(URI url) { + this.url = checkNotNull(url, "url"); + return this; + } + + public Builder checksum(byte[] checksum) { + this.checksum = checkNotNull(checksum, "checksum"); + return this; + } + + public Builder path(String path) { + this.path = checkNotNull(path, "path"); + return this; + } + + public Builder specificity(String specificity) { + this.specificity = checkNotNull(specificity, "specificity"); + return this; + } + + public Builder fromPayload(FilePayload payload) { + checkNotNull(payload, "payload"); + this.name(payload.getRawContent().getName()); + this.checksum(payload.getContentMetadata().getContentMD5()); + this.path(payload.getRawContent().getPath()); + return this; + } + + public Resource build() { + return new Resource(name, url, checksum, path, specificity); + } + } + + private final String name; + private final URI url; + private final byte[] checksum; + private final String path; + private final String specificity; + + @ConstructorProperties({ "name", "url", "checksum", "path", "specificity" }) + protected Resource(String name, URI url, byte[] checksum, String path, String specificity) { + this.name = name; + this.url = url; + this.checksum = checksum; + this.path = path; + this.specificity = specificity; + } + + public String getName() { + return name; + } + + public URI getUrl() { + return url; + } + + public byte[] getChecksum() { + return checksum; + } + + public String getPath() { + return path; + } + + public String getSpecificity() { + return specificity; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + Arrays.hashCode(checksum); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((path == null) ? 0 : path.hashCode()); + result = prime * result + ((specificity == null) ? 0 : specificity.hashCode()); + result = prime * result + ((url == null) ? 0 : url.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Resource other = (Resource) obj; + if (!Arrays.equals(checksum, other.checksum)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (path == null) { + if (other.path != null) + return false; + } else if (!path.equals(other.path)) + return false; + if (specificity == null) { + if (other.specificity != null) + return false; + } else if (!specificity.equals(other.specificity)) + return false; + if (url == null) { + if (other.url != null) + return false; + } else if (!url.equals(other.url)) + return false; + return true; + } + + @Override + public String toString() { + return "Resource [checksum=" + Bytes.asList(checksum) + ", name=" + name + ", path=" + path + ", specificity=" + + specificity + ", url=" + url + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Role.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Role.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Role.java new file mode 100644 index 0000000..d51dc1e --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Role.java @@ -0,0 +1,205 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.util.List; +import java.util.Map; + +import org.jclouds.domain.JsonBall; +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * Role object. + */ +public class Role { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String name; + private String description; + private ImmutableMap.Builder<String, JsonBall> overrideAttributes = ImmutableMap.builder(); + private ImmutableMap.Builder<String, JsonBall> defaultAttributes = ImmutableMap.builder(); + private ImmutableList.Builder<String> runList = ImmutableList.builder(); + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + + public Builder overrideAttribute(String key, JsonBall value) { + this.overrideAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder overrideAttributes(Map<String, JsonBall> overrideAttributes) { + this.overrideAttributes.putAll(checkNotNull(overrideAttributes, "overrideAttributes")); + return this; + } + + public Builder defaultAttribute(String key, JsonBall value) { + this.defaultAttributes.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder defaultAttributes(Map<String, JsonBall> defaultAttributes) { + this.defaultAttributes.putAll(checkNotNull(defaultAttributes, "defaultAttributes")); + return this; + } + + public Builder runListElement(String element) { + this.runList.add(checkNotNull(element, "element")); + return this; + } + + public Builder runList(Iterable<String> runList) { + this.runList.addAll(checkNotNull(runList, "runList")); + return this; + } + + public Role build() { + return new Role(name, description, defaultAttributes.build(), runList.build(), overrideAttributes.build()); + } + } + + private final String name; + private final String description; + @SerializedName("override_attributes") + private final Map<String, JsonBall> overrideAttributes; + @SerializedName("default_attributes") + private final Map<String, JsonBall> defaultAttributes; + @SerializedName("run_list") + private final List<String> runList; + + // internal + @SerializedName("json_class") + private final String _jsonClass = "Chef::Role"; + @SerializedName("chef_type") + private final String _chefType = "role"; + + @ConstructorProperties({ "name", "description", "default_attributes", "run_list", "override_attributes" }) + protected Role(String name, String description, @Nullable Map<String, JsonBall> defaultAttributes, + @Nullable List<String> runList, @Nullable Map<String, JsonBall> overrideAttributes) { + this.name = name; + this.description = description; + this.defaultAttributes = copyOfOrEmpty(defaultAttributes); + this.runList = copyOfOrEmpty(runList); + this.overrideAttributes = copyOfOrEmpty(overrideAttributes); + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Map<String, JsonBall> getOverrideAttributes() { + return overrideAttributes; + } + + public Map<String, JsonBall> getDefaultAttributes() { + return defaultAttributes; + } + + public List<String> getRunList() { + return runList; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((_chefType == null) ? 0 : _chefType.hashCode()); + result = prime * result + ((_jsonClass == null) ? 0 : _jsonClass.hashCode()); + result = prime * result + ((defaultAttributes == null) ? 0 : defaultAttributes.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((overrideAttributes == null) ? 0 : overrideAttributes.hashCode()); + result = prime * result + ((runList == null) ? 0 : runList.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Role other = (Role) obj; + if (_chefType == null) { + if (other._chefType != null) + return false; + } else if (!_chefType.equals(other._chefType)) + return false; + if (_jsonClass == null) { + if (other._jsonClass != null) + return false; + } else if (!_jsonClass.equals(other._jsonClass)) + return false; + if (defaultAttributes == null) { + if (other.defaultAttributes != null) + return false; + } else if (!defaultAttributes.equals(other.defaultAttributes)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (overrideAttributes == null) { + if (other.overrideAttributes != null) + return false; + } else if (!overrideAttributes.equals(other.overrideAttributes)) + return false; + if (runList == null) { + if (other.runList != null) + return false; + } else if (!runList.equals(other.runList)) + return false; + return true; + } + + @Override + public String toString() { + return "Role [name=" + name + ", description=" + description + ", defaultAttributes=" + defaultAttributes + + ", overrideAttributes=" + overrideAttributes + ", runList=" + runList + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/Sandbox.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/Sandbox.java b/apis/chef/src/main/java/org/jclouds/chef/domain/Sandbox.java new file mode 100644 index 0000000..c58d02d --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/Sandbox.java @@ -0,0 +1,195 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.util.Date; +import java.util.Set; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableSet; +import com.google.gson.annotations.SerializedName; + +/** + * Sandbox object. + */ +public class Sandbox { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String rev; + private boolean isCompleted; + private Date createTime; + private ImmutableSet.Builder<String> checksums = ImmutableSet.builder(); + private String name; + private String guid; + + public Builder rev(String rev) { + this.rev = checkNotNull(rev, "rev"); + return this; + } + + public Builder isCompleted(boolean isCompleted) { + this.isCompleted = isCompleted; + return this; + } + + public Builder createTime(Date createTime) { + this.createTime = createTime; + return this; + } + + public Builder checksum(String checksum) { + this.checksums.add(checkNotNull(checksum, "checksum")); + return this; + } + + public Builder checksums(Iterable<String> checksums) { + this.checksums.addAll(checkNotNull(checksums, "checksums")); + return this; + } + + public Builder name(String name) { + this.name = checkNotNull(name, "name"); + return this; + } + + public Builder guid(String guid) { + this.guid = checkNotNull(guid, "guid"); + return this; + } + + public Sandbox build() { + return new Sandbox(rev, isCompleted, createTime, checksums.build(), name, guid); + } + } + + @SerializedName("_rev") + private final String rev; + @SerializedName("is_completed") + private final boolean isCompleted; + @SerializedName("create_time") + private final Date createTime; + private final Set<String> checksums; + private final String name; + private final String guid; + + // internal + @SerializedName("json_class") + private final String _jsonClass = "Chef::Sandbox"; + @SerializedName("chef_type") + private final String _chefType = "sandbox"; + + @ConstructorProperties({ "_rev", "is_completed", "create_time", "checksums", "name", "guid" }) + protected Sandbox(String rev, boolean isCompleted, Date createTime, @Nullable Set<String> checksums, String name, + String guid) { + this.rev = rev; + this.isCompleted = isCompleted; + this.createTime = createTime; + this.checksums = copyOfOrEmpty(checksums); + this.name = name; + this.guid = guid; + } + + public String getRev() { + return rev; + } + + public boolean isCompleted() { + return isCompleted; + } + + public Date getCreateTime() { + return createTime; + } + + public Set<String> getChecksums() { + return checksums; + } + + public String getName() { + return name; + } + + public String getGuid() { + return guid; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((checksums == null) ? 0 : checksums.hashCode()); + result = prime * result + ((createTime == null) ? 0 : createTime.hashCode()); + result = prime * result + ((guid == null) ? 0 : guid.hashCode()); + result = prime * result + (isCompleted ? 1231 : 1237); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((rev == null) ? 0 : rev.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Sandbox other = (Sandbox) obj; + if (checksums == null) { + if (other.checksums != null) + return false; + } else if (!checksums.equals(other.checksums)) + return false; + if (createTime == null) { + if (other.createTime != null) + return false; + } else if (!createTime.equals(other.createTime)) + return false; + if (guid == null) { + if (other.guid != null) + return false; + } else if (!guid.equals(other.guid)) + return false; + if (isCompleted != other.isCompleted) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (rev == null) { + if (other.rev != null) + return false; + } else if (!rev.equals(other.rev)) + return false; + return true; + } + + @Override + public String toString() { + return "Sandbox [checksums=" + checksums + ", createTime=" + createTime + ", guid=" + guid + ", isCompleted=" + + isCompleted + ", name=" + name + ", rev=" + rev + "]"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/SearchResult.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/SearchResult.java b/apis/chef/src/main/java/org/jclouds/chef/domain/SearchResult.java new file mode 100644 index 0000000..7e406c1 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/SearchResult.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import java.util.LinkedHashSet; + +import com.google.common.collect.Iterables; + +/** + * A result of a search. + */ +public class SearchResult<T> extends LinkedHashSet<T> { + private static final long serialVersionUID = 4000610660948065287L; + private long start; + + SearchResult() { + } + + public SearchResult(long start, Iterable<T> results) { + this.start = start; + Iterables.addAll(this, results); + } + + /** + * + * @return the result position this started from from + */ + long getStart() { + return start; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/domain/UploadSandbox.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/domain/UploadSandbox.java b/apis/chef/src/main/java/org/jclouds/chef/domain/UploadSandbox.java new file mode 100644 index 0000000..9ca4c0f --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/domain/UploadSandbox.java @@ -0,0 +1,136 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.domain; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.jclouds.chef.util.CollectionUtils.copyOfOrEmpty; + +import java.beans.ConstructorProperties; +import java.net.URI; +import java.util.List; +import java.util.Map; + +import org.jclouds.javax.annotation.Nullable; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.annotations.SerializedName; + +/** + * An upload sandbox. + */ +public class UploadSandbox { + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private URI uri; + private ImmutableMap.Builder<List<Byte>, ChecksumStatus> checksums = ImmutableMap.builder(); + private String sandboxId; + + public Builder uri(URI uri) { + this.uri = checkNotNull(uri, "uri"); + return this; + } + + public Builder checksum(List<Byte> key, ChecksumStatus value) { + this.checksums.put(checkNotNull(key, "key"), checkNotNull(value, "value")); + return this; + } + + public Builder checksums(Map<List<Byte>, ChecksumStatus> checksums) { + this.checksums.putAll(checkNotNull(checksums, "checksums")); + return this; + } + + public Builder sandboxId(String sandboxId) { + this.sandboxId = checkNotNull(sandboxId, "sandboxId"); + return this; + } + + public UploadSandbox build() { + return new UploadSandbox(uri, checksums.build(), sandboxId); + } + } + + private final URI uri; + private final Map<List<Byte>, ChecksumStatus> checksums; + @SerializedName("sandbox_id") + private final String sandboxId; + + @ConstructorProperties({ "uri", "checksums", "sandbox_id" }) + protected UploadSandbox(URI uri, @Nullable Map<List<Byte>, ChecksumStatus> checksums, String sandboxId) { + this.uri = uri; + this.checksums = copyOfOrEmpty(checksums); + this.sandboxId = sandboxId; + } + + public URI getUri() { + return uri; + } + + public Map<List<Byte>, ChecksumStatus> getChecksums() { + return checksums; + } + + public String getSandboxId() { + return sandboxId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((checksums == null) ? 0 : checksums.hashCode()); + result = prime * result + ((sandboxId == null) ? 0 : sandboxId.hashCode()); + result = prime * result + ((uri == null) ? 0 : uri.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + UploadSandbox other = (UploadSandbox) obj; + if (checksums == null) { + if (other.checksums != null) + return false; + } else if (!checksums.equals(other.checksums)) + return false; + if (sandboxId == null) { + if (other.sandboxId != null) + return false; + } else if (!sandboxId.equals(other.sandboxId)) + return false; + if (uri == null) { + if (other.uri != null) + return false; + } else if (!uri.equals(other.uri)) + return false; + return true; + } + + @Override + public String toString() { + return "UploadSandbox [checksums=" + checksums + ", id=" + sandboxId + ", uri=" + uri + "]"; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java b/apis/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java new file mode 100644 index 0000000..cabe579 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/filters/SignedHeaderAuth.java @@ -0,0 +1,200 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.filters; + +import static com.google.common.base.Charsets.UTF_8; +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.hash.Hashing.sha1; +import static com.google.common.io.BaseEncoding.base64; +import static com.google.common.io.ByteStreams.toByteArray; + +import java.io.IOException; +import java.security.PrivateKey; +import java.util.NoSuchElementException; + +import javax.annotation.Resource; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.jclouds.Constants; +import org.jclouds.crypto.Crypto; +import org.jclouds.date.TimeStamp; +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.HttpUtils; +import org.jclouds.http.internal.SignatureWire; +import org.jclouds.io.ByteStreams2; +import org.jclouds.io.Payload; +import org.jclouds.io.Payloads; +import org.jclouds.io.payloads.MultipartForm; +import org.jclouds.io.payloads.Part; +import org.jclouds.io.payloads.RSAEncryptingPayload; +import org.jclouds.logging.Logger; +import org.jclouds.util.Strings2; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Predicate; +import com.google.common.base.Splitter; +import com.google.common.base.Supplier; +import com.google.common.base.Throwables; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.Iterables; +import com.google.common.collect.Multimap; +import com.google.common.io.ByteSource; + +/** + * Ported from mixlib-authentication in order to sign Chef requests. + * + * @see <a href= "http://github.com/opscode/mixlib-authentication" /> + */ +@Singleton +public class SignedHeaderAuth implements HttpRequestFilter { + public static final String SIGNING_DESCRIPTION = "version=1.0"; + + private final SignatureWire signatureWire; + private final Supplier<Credentials> creds; + private final Supplier<PrivateKey> supplyKey; + private final Provider<String> timeStampProvider; + private final String emptyStringHash; + private final HttpUtils utils; + private final Crypto crypto; + + @Resource + @Named(Constants.LOGGER_SIGNATURE) + Logger signatureLog = Logger.NULL; + + @Inject + public SignedHeaderAuth(SignatureWire signatureWire, @org.jclouds.location.Provider Supplier<Credentials> creds, + Supplier<PrivateKey> supplyKey, @TimeStamp Provider<String> timeStampProvider, HttpUtils utils, Crypto crypto) { + this.signatureWire = checkNotNull(signatureWire, "signatureWire"); + this.creds = checkNotNull(creds, "creds"); + this.supplyKey = checkNotNull(supplyKey, "supplyKey"); + this.timeStampProvider = checkNotNull(timeStampProvider, "timeStampProvider"); + this.emptyStringHash = hashBody(Payloads.newStringPayload("")); + this.utils = checkNotNull(utils, "utils"); + this.crypto = checkNotNull(crypto, "crypto"); + } + + public HttpRequest filter(HttpRequest input) throws HttpException { + HttpRequest request = input.toBuilder().endpoint(input.getEndpoint().toString().replace("%3F", "?")).build(); + String contentHash = hashBody(request.getPayload()); + Multimap<String, String> headers = ArrayListMultimap.create(); + headers.put("X-Ops-Content-Hash", contentHash); + String timestamp = timeStampProvider.get(); + String toSign = createStringToSign(request.getMethod(), hashPath(request.getEndpoint().getPath()), contentHash, + timestamp); + headers.put("X-Ops-Userid", creds.get().identity); + headers.put("X-Ops-Sign", SIGNING_DESCRIPTION); + request = calculateAndReplaceAuthorizationHeaders(request, toSign); + headers.put("X-Ops-Timestamp", timestamp); + utils.logRequest(signatureLog, request, "<<"); + + return request.toBuilder().replaceHeaders(headers).build(); + } + + @VisibleForTesting + HttpRequest calculateAndReplaceAuthorizationHeaders(HttpRequest request, String toSign) throws HttpException { + String signature = sign(toSign); + if (signatureWire.enabled()) + signatureWire.input(Strings2.toInputStream(signature)); + String[] signatureLines = Iterables.toArray(Splitter.fixedLength(60).split(signature), String.class); + + Multimap<String, String> headers = ArrayListMultimap.create(); + for (int i = 0; i < signatureLines.length; i++) { + headers.put("X-Ops-Authorization-" + (i + 1), signatureLines[i]); + } + return request.toBuilder().replaceHeaders(headers).build(); + } + + public String createStringToSign(String request, String hashedPath, String contentHash, String timestamp) { + + return new StringBuilder().append("Method:").append(request).append("\n").append("Hashed Path:") + .append(hashedPath).append("\n").append("X-Ops-Content-Hash:").append(contentHash).append("\n") + .append("X-Ops-Timestamp:").append(timestamp).append("\n").append("X-Ops-UserId:") + .append(creds.get().identity).toString(); + + } + + @VisibleForTesting + String hashPath(String path) { + try { + return base64().encode(ByteSource.wrap(canonicalPath(path).getBytes(UTF_8)).hash(sha1()).asBytes()); + } catch (Exception e) { + Throwables.propagateIfPossible(e); + throw new HttpException("error creating sigature for path: " + path, e); + } + } + + /** + * Build the canonicalized path, which collapses multiple slashes (/) and + * removes a trailing slash unless the path is only "/" + */ + @VisibleForTesting + String canonicalPath(String path) { + path = path.replaceAll("\\/+", "/"); + return path.endsWith("/") && path.length() > 1 ? path.substring(0, path.length() - 1) : path; + } + + @VisibleForTesting + String hashBody(Payload payload) { + if (payload == null) + return emptyStringHash; + payload = useTheFilePartIfForm(payload); + checkArgument(payload != null, "payload was null"); + checkArgument(payload.isRepeatable(), "payload must be repeatable: " + payload); + try { + return base64().encode(ByteStreams2.hashAndClose(payload.getInput(), sha1()).asBytes()); + } catch (Exception e) { + Throwables.propagateIfPossible(e); + throw new HttpException("error creating sigature for payload: " + payload, e); + } + } + + private Payload useTheFilePartIfForm(Payload payload) { + if (payload instanceof MultipartForm) { + Iterable<? extends Part> parts = MultipartForm.class.cast(payload).getRawContent(); + try { + payload = Iterables.find(parts, new Predicate<Part>() { + + @Override + public boolean apply(Part input) { + return "file".equals(input.getName()); + } + + }); + } catch (NoSuchElementException e) { + + } + } + return payload; + } + + public String sign(String toSign) { + try { + byte[] encrypted = toByteArray(new RSAEncryptingPayload(crypto, Payloads.newStringPayload(toSign), supplyKey.get())); + return base64().encode(encrypted); + } catch (IOException e) { + throw new HttpException("error signing request", e); + } + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/BootstrapConfigForGroup.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/BootstrapConfigForGroup.java b/apis/chef/src/main/java/org/jclouds/chef/functions/BootstrapConfigForGroup.java new file mode 100644 index 0000000..ec75e47 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/BootstrapConfigForGroup.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; +import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG; + +import java.lang.reflect.Type; +import java.util.Map; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.jclouds.chef.ChefApi; +import org.jclouds.chef.domain.DatabagItem; +import org.jclouds.domain.JsonBall; + +import com.google.common.base.Function; +import com.google.inject.TypeLiteral; + +/** + * + * Retrieves the bootstrap configuration for a specific group + */ +@Singleton +public class BootstrapConfigForGroup implements Function<String, DatabagItem> { + public static final Type BOOTSTRAP_CONFIG_TYPE = new TypeLiteral<Map<String, JsonBall>>() { + }.getType(); + private final ChefApi api; + private final String databag; + + @Inject + public BootstrapConfigForGroup(@Named(CHEF_BOOTSTRAP_DATABAG) String databag, ChefApi api) { + this.databag = checkNotNull(databag, "databag"); + this.api = checkNotNull(api, "api"); + } + + @Override + public DatabagItem apply(String from) { + DatabagItem bootstrapConfig = api.getDatabagItem(databag, from); + checkState(bootstrapConfig != null, "databag item %s/%s not found", databag, from); + return bootstrapConfig; + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ClientForGroup.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ClientForGroup.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ClientForGroup.java new file mode 100644 index 0000000..d1a9250 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ClientForGroup.java @@ -0,0 +1,69 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Sets.newHashSet; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.chef.ChefApi; +import org.jclouds.chef.domain.Client; + +import com.google.common.base.Function; + +/** + * + * Generates a client relevant for a particular group + */ +@Singleton +public class ClientForGroup implements Function<String, Client> { + private final ChefApi chefApi; + + @Inject + public ClientForGroup(ChefApi chefApi) { + this.chefApi = checkNotNull(chefApi, "chefApi"); + } + + @Override + public Client apply(String from) { + String clientName = findNextClientName(chefApi.listClients(), from + "-client-%02d"); + Client client = chefApi.createClient(clientName); + // response from create only includes the key + return Client.builder() // + .clientname(clientName) // + .name(clientName) // + .isValidator(false) // + .privateKey(client.getPrivateKey()) // + .build(); + } + + private static String findNextClientName(Set<String> clients, String pattern) { + String clientName; + Set<String> names = newHashSet(clients); + int index = 0; + while (true) { + clientName = String.format(pattern, index++); + if (!names.contains(clientName)) + break; + } + return clientName; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/GroupToBootScript.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/GroupToBootScript.java b/apis/chef/src/main/java/org/jclouds/chef/functions/GroupToBootScript.java new file mode 100644 index 0000000..516d9f9 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/GroupToBootScript.java @@ -0,0 +1,130 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.propagate; +import static org.jclouds.scriptbuilder.domain.Statements.appendFile; +import static org.jclouds.scriptbuilder.domain.Statements.exec; +import static org.jclouds.scriptbuilder.domain.Statements.newStatementList; + +import java.lang.reflect.Type; +import java.net.URI; +import java.security.PrivateKey; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.chef.config.InstallChef; +import org.jclouds.chef.config.Validator; +import org.jclouds.crypto.Pems; +import org.jclouds.domain.JsonBall; +import org.jclouds.json.Json; +import org.jclouds.location.Provider; +import org.jclouds.scriptbuilder.ExitInsteadOfReturn; +import org.jclouds.scriptbuilder.domain.Statement; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import com.google.common.base.Splitter; +import com.google.common.base.Supplier; +import com.google.common.cache.CacheLoader; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.inject.TypeLiteral; + +/** + * + * Generates a bootstrap script relevant for a particular group + */ +@Singleton +public class GroupToBootScript implements Function<String, Statement> { + private static final Pattern newLinePattern = Pattern.compile("(\\r\\n)|(\\n)"); + + @VisibleForTesting + static final Type RUN_LIST_TYPE = new TypeLiteral<Map<String, List<String>>>() { + }.getType(); + private final Supplier<URI> endpoint; + private final Json json; + private final CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup; + private final Statement installChef; + private final Optional<String> validatorName; + private final Optional<PrivateKey> validatorCredential; + + @Inject + public GroupToBootScript(@Provider Supplier<URI> endpoint, Json json, + CacheLoader<String, ? extends JsonBall> bootstrapConfigForGroup, + @InstallChef Statement installChef, @Validator Optional<String> validatorName, + @Validator Optional<PrivateKey> validatorCredential) { + this.endpoint = checkNotNull(endpoint, "endpoint"); + this.json = checkNotNull(json, "json"); + this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup"); + this.installChef = checkNotNull(installChef, "installChef"); + this.validatorName = checkNotNull(validatorName, "validatorName"); + this.validatorCredential = checkNotNull(validatorCredential, validatorCredential); + } + + @Override + public Statement apply(String group) { + checkNotNull(group, "group"); + String validatorClientName = validatorName.get(); + PrivateKey validatorKey = validatorCredential.get(); + + JsonBall bootstrapConfig = null; + try { + bootstrapConfig = bootstrapConfigForGroup.load(group); + } catch (Exception e) { + throw propagate(e); + } + + Map<String, JsonBall> config = json.fromJson(bootstrapConfig.toString(), + BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE); + Optional<JsonBall> environment = Optional.fromNullable(config.get("environment")); + + String chefConfigDir = "{root}etc{fs}chef"; + Statement createChefConfigDir = exec("{md} " + chefConfigDir); + Statement createClientRb = appendFile(chefConfigDir + "{fs}client.rb", ImmutableList.of("require 'rubygems'", + "require 'ohai'", "o = Ohai::System.new", "o.all_plugins", + String.format("node_name \"%s-\" + o[:ipaddress]", group), "log_level :info", "log_location STDOUT", + String.format("validation_client_name \"%s\"", validatorClientName), + String.format("chef_server_url \"%s\"", endpoint.get()))); + + Statement createValidationPem = appendFile(chefConfigDir + "{fs}validation.pem", + Splitter.on(newLinePattern).split(Pems.pem(validatorKey))); + + String chefBootFile = chefConfigDir + "{fs}first-boot.json"; + Statement createFirstBoot = appendFile(chefBootFile, Collections.singleton(json.toJson(bootstrapConfig))); + + ImmutableMap.Builder<String, String> options = ImmutableMap.builder(); + options.put("-j", chefBootFile); + if (environment.isPresent()) { + options.put("-E", environment.get().toString()); + } + String strOptions = Joiner.on(' ').withKeyValueSeparator(" ").join(options.build()); + Statement runChef = exec("chef-client " + strOptions); + + return newStatementList(new ExitInsteadOfReturn(installChef), createChefConfigDir, createClientRb, createValidationPem, + createFirstBoot, runChef); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersion.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersion.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersion.java new file mode 100644 index 0000000..ffb4201 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionCheckingChefVersion.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.chef.config.CookbookParser; +import org.jclouds.http.HttpResponse; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Function; + +/** + * Parses a cookbook definition from a Json response, taking care of using the + * appropriate parser. + */ +@Singleton +public class ParseCookbookDefinitionCheckingChefVersion implements Function<HttpResponse, Set<String>> { + + @VisibleForTesting + final Function<HttpResponse, Set<String>> parser; + + @Inject + ParseCookbookDefinitionCheckingChefVersion(@CookbookParser Function<HttpResponse, Set<String>> parser) { + this.parser = parser; + } + + @Override + public Set<String> apply(HttpResponse response) { + return parser.apply(response); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJson.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJson.java new file mode 100644 index 0000000..3e172e4 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJson.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.chef.domain.CookbookDefinition; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; + +import com.google.common.base.Function; + +/** + * Parses a cookbook definition from a Json response, assuming a Chef Server >= + * 0.10.8. + */ +@Singleton +public class ParseCookbookDefinitionFromJson implements Function<HttpResponse, Set<String>> { + + /** Parser for responses from chef server >= 0.10.8 */ + private final ParseJson<Map<String, CookbookDefinition>> parser; + + @Inject + ParseCookbookDefinitionFromJson(ParseJson<Map<String, CookbookDefinition>> parser) { + this.parser = parser; + } + + @Override + public Set<String> apply(HttpResponse response) { + return parser.apply(response).keySet(); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10.java ---------------------------------------------------------------------- diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10.java new file mode 100644 index 0000000..692d969 --- /dev/null +++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionFromJsonv10.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.chef.functions; + +import com.google.common.base.Function; +import org.jclouds.chef.domain.CookbookDefinition; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.functions.ParseJson; + +import javax.inject.Inject; +import javax.inject.Singleton; +import java.util.Map; + +/** + * Parses the cookbook versions in a Chef Server >= 0.10.8. + */ +@Singleton +public class ParseCookbookDefinitionFromJsonv10 implements Function<HttpResponse, CookbookDefinition> { + + /** Parser for responses from chef server >= 0.10.8 */ + private final ParseJson<Map<String, CookbookDefinition>> parser; + + @Inject + ParseCookbookDefinitionFromJsonv10(ParseJson<Map<String, CookbookDefinition>> parser) { + this.parser = parser; + } + + @Override + public CookbookDefinition apply(HttpResponse response) { + Map<String, CookbookDefinition> result = parser.apply(response); + String cookbookName = result.keySet().iterator().next(); + CookbookDefinition def = result.values().iterator().next(); + return CookbookDefinition.builder() // + .from(def) // + .name(cookbookName) // + .build(); + } +}
