You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2014/07/28 22:02:58 UTC
[07/10] Move jclouds-chef to the main jclouds repo
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10.java
new file mode 100644
index 0000000..5da0797
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookDefinitionListFromJsonv10.java
@@ -0,0 +1,63 @@
+/*
+ * 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;
+import java.util.Set;
+
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.newLinkedHashSet;
+
+/**
+ * Parses the cookbook versions in a Chef Server >= 0.10.8.
+ */
+@Singleton
+public class ParseCookbookDefinitionListFromJsonv10 implements Function<HttpResponse, Set<CookbookDefinition>> {
+
+ /**
+ * Parser for responses from chef server >= 0.10.8
+ */
+ private final ParseJson<Map<String, CookbookDefinition>> parser;
+
+ @Inject
+ ParseCookbookDefinitionListFromJsonv10(ParseJson<Map<String, CookbookDefinition>> parser) {
+ this.parser = parser;
+ }
+
+ @Override
+ public Set<CookbookDefinition> apply(HttpResponse response) {
+ Set<Map.Entry<String, CookbookDefinition>> result = parser.apply(response).entrySet();
+ return newLinkedHashSet(transform(result, new Function<Map.Entry<String, CookbookDefinition>, CookbookDefinition>() {
+ @Override
+ public CookbookDefinition apply(Map.Entry<String, CookbookDefinition> input) {
+ String cookbookName = input.getKey();
+ CookbookDefinition def = input.getValue();
+ return CookbookDefinition.builder() //
+ .from(def) //
+ .name(cookbookName) //
+ .build();
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersion.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersion.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersion.java
new file mode 100644
index 0000000..f82a900
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsCheckingChefVersion.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.CookbookVersionsParser;
+import org.jclouds.http.HttpResponse;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+
+/**
+ * Parses a cookbook versions from a Json response, taking care of using the
+ * appropriate parser.
+ */
+@Singleton
+public class ParseCookbookVersionsCheckingChefVersion implements Function<HttpResponse, Set<String>> {
+
+ @VisibleForTesting
+ final Function<HttpResponse, Set<String>> parser;
+
+ @Inject
+ ParseCookbookVersionsCheckingChefVersion(@CookbookVersionsParser 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/ParseCookbookVersionsV09FromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJson.java
new file mode 100644
index 0000000..4421b3e
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV09FromJson.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.Map;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+
+import com.google.common.base.Function;
+import static com.google.common.collect.Iterables.getFirst;
+
+/**
+ * Parses the cookbook versions in a Chef Server <= 0.9.8.
+ */
+@Singleton
+public class ParseCookbookVersionsV09FromJson implements Function<HttpResponse, Set<String>> {
+
+ private final ParseJson<Map<String, Set<String>>> json;
+
+ @Inject
+ ParseCookbookVersionsV09FromJson(ParseJson<Map<String, Set<String>>> json) {
+ this.json = json;
+ }
+
+ @Override
+ public Set<String> apply(HttpResponse response) {
+ return getFirst(json.apply(response).values(), null);
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJson.java
new file mode 100644
index 0000000..1a25ac0
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseCookbookVersionsV10FromJson.java
@@ -0,0 +1,59 @@
+/*
+ * 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.chef.domain.CookbookDefinition.Version;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+
+import com.google.common.base.Function;
+import static com.google.common.collect.Iterables.getFirst;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.collect.Sets.newLinkedHashSet;
+
+/**
+ * Parses the cookbook versions in a Chef Server >= 0.10.8.
+ */
+@Singleton
+public class ParseCookbookVersionsV10FromJson implements Function<HttpResponse, Set<String>> {
+
+ /** Parser for responses from chef server >= 0.10.8 */
+ private final ParseJson<Map<String, CookbookDefinition>> parser;
+
+ @Inject
+ ParseCookbookVersionsV10FromJson(ParseJson<Map<String, CookbookDefinition>> parser) {
+ this.parser = parser;
+ }
+
+ @Override
+ public Set<String> apply(HttpResponse response) {
+ CookbookDefinition def = getFirst(parser.apply(response).values(), null);
+ return newLinkedHashSet(transform(def.getVersions(), new Function<Version, String>() {
+ @Override
+ public String apply(Version input) {
+ return input.getVersion();
+ }
+ }));
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBody.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBody.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBody.java
new file mode 100644
index 0000000..6440409
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseErrorFromJsonOrReturnBody.java
@@ -0,0 +1,55 @@
+/*
+ * 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.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ReturnStringIf2xx;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class ParseErrorFromJsonOrReturnBody implements Function<HttpResponse, String> {
+ Pattern pattern = Pattern.compile(".*\\[\"([^\"]+)\"\\].*");
+ private final ReturnStringIf2xx returnStringIf200;
+
+ @Inject
+ ParseErrorFromJsonOrReturnBody(ReturnStringIf2xx returnStringIf200) {
+ this.returnStringIf200 = returnStringIf200;
+ }
+
+ @Override
+ public String apply(HttpResponse response) {
+ String content = returnStringIf200.apply(response);
+ if (content == null)
+ return null;
+ return parse(content);
+ }
+
+ public String parse(String in) {
+ Matcher matcher = pattern.matcher(in);
+ if (matcher.find()) {
+ return matcher.group(1);
+ }
+ return in;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseKeySetFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseKeySetFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseKeySetFromJson.java
new file mode 100644
index 0000000..963c19b
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseKeySetFromJson.java
@@ -0,0 +1,45 @@
+/*
+ * 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.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class ParseKeySetFromJson implements Function<HttpResponse, Set<String>> {
+
+ private final ParseJson<Map<String, String>> json;
+
+ @Inject
+ ParseKeySetFromJson(ParseJson<Map<String, String>> json) {
+ this.json = json;
+ }
+
+ @Override
+ public Set<String> apply(HttpResponse response) {
+ return json.apply(response).keySet();
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchClientsFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchClientsFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchClientsFromJson.java
new file mode 100644
index 0000000..18ecbfa
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchClientsFromJson.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Client;
+import org.jclouds.http.functions.ParseJson;
+
+@Singleton
+public class ParseSearchClientsFromJson extends ParseSearchResultFromJson<Client> {
+
+ // TODO add generic json parser detector
+
+ @Inject
+ ParseSearchClientsFromJson(ParseJson<Response<Client>> json) {
+ super(json);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchDatabagFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchDatabagFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchDatabagFromJson.java
new file mode 100644
index 0000000..c2c58ef
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchDatabagFromJson.java
@@ -0,0 +1,77 @@
+/*
+ * 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.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.chef.domain.SearchResult;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+
+import com.google.common.base.Function;
+import com.google.gson.annotations.SerializedName;
+import static com.google.common.collect.Iterables.transform;
+
+/**
+ * Parses the search result into a {@link DatabagItem} object.
+ * <p>
+ * When searching databags, the items are contained inside the
+ * <code>raw_data</code> list.
+ */
+@Singleton
+public class ParseSearchDatabagFromJson implements Function<HttpResponse, SearchResult<DatabagItem>> {
+
+ private final ParseJson<Response> responseParser;
+
+ private final Json json;
+
+ static class Row {
+ @SerializedName("raw_data")
+ JsonBall rawData;
+ }
+
+ static class Response {
+ long start;
+ List<Row> rows;
+ }
+
+ @Inject
+ ParseSearchDatabagFromJson(ParseJson<Response> responseParser, Json json) {
+ this.responseParser = responseParser;
+ this.json = json;
+ }
+
+ @Override
+ public SearchResult<DatabagItem> apply(HttpResponse response) {
+ Response returnVal = responseParser.apply(response);
+ Iterable<DatabagItem> items = transform(returnVal.rows, new Function<Row, DatabagItem>() {
+ @Override
+ public DatabagItem apply(Row input) {
+ return json.fromJson(input.rawData.toString(), DatabagItem.class);
+ }
+ });
+
+ return new SearchResult<DatabagItem>(returnVal.start, items);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchEnvironmentsFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchEnvironmentsFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchEnvironmentsFromJson.java
new file mode 100644
index 0000000..852e0f3
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchEnvironmentsFromJson.java
@@ -0,0 +1,35 @@
+/*
+ * 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 org.jclouds.chef.domain.Environment;
+import org.jclouds.http.functions.ParseJson;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+@Singleton
+public class ParseSearchEnvironmentsFromJson extends ParseSearchResultFromJson<Environment> {
+
+ // TODO add generic json parser detector
+
+ @Inject
+ ParseSearchEnvironmentsFromJson(ParseJson<Response<Environment>> json) {
+ super(json);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchNodesFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchNodesFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchNodesFromJson.java
new file mode 100644
index 0000000..6d34575
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchNodesFromJson.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Node;
+import org.jclouds.http.functions.ParseJson;
+
+@Singleton
+public class ParseSearchNodesFromJson extends ParseSearchResultFromJson<Node> {
+
+ // TODO add generic json parser detector
+
+ @Inject
+ ParseSearchNodesFromJson(ParseJson<Response<Node>> json) {
+ super(json);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchResultFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchResultFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchResultFromJson.java
new file mode 100644
index 0000000..6c9bd84
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchResultFromJson.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.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.SearchResult;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseJson;
+
+import com.google.common.base.Function;
+
+@Singleton
+public class ParseSearchResultFromJson<T> implements Function<HttpResponse, SearchResult<T>> {
+
+ private final ParseJson<Response<T>> json;
+
+ static class Response<T> {
+ long start;
+ List<T> rows;
+ }
+
+ @Inject
+ ParseSearchResultFromJson(ParseJson<Response<T>> json) {
+ this.json = json;
+ }
+
+ @Override
+ public SearchResult<T> apply(HttpResponse response) {
+ Response<T> returnVal = json.apply(response);
+ return new SearchResult<T>(returnVal.start, returnVal.rows);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchRolesFromJson.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchRolesFromJson.java b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchRolesFromJson.java
new file mode 100644
index 0000000..42ba797
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/ParseSearchRolesFromJson.java
@@ -0,0 +1,35 @@
+/*
+ * 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 javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Role;
+import org.jclouds.http.functions.ParseJson;
+
+@Singleton
+public class ParseSearchRolesFromJson extends ParseSearchResultFromJson<Role> {
+
+ // TODO add generic json parser detector
+
+ @Inject
+ ParseSearchRolesFromJson(ParseJson<Response<Role>> json) {
+ super(json);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/RunListForGroup.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/RunListForGroup.java b/apis/chef/src/main/java/org/jclouds/chef/functions/RunListForGroup.java
new file mode 100644
index 0000000..b14ae71
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/RunListForGroup.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 java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.json.Json;
+
+import com.google.common.base.Function;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Retrieves the run-list for a specific group
+ */
+@Singleton
+public class RunListForGroup implements Function<String, List<String>> {
+ public static final Type RUN_LIST_TYPE = new TypeLiteral<List<String>>() {
+ }.getType();
+ private final BootstrapConfigForGroup bootstrapConfigForGroup;
+
+ private final Json json;
+
+ @Inject
+ public RunListForGroup(BootstrapConfigForGroup bootstrapConfigForGroup, Json json) {
+ this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup");
+ this.json = checkNotNull(json, "json");
+ }
+
+ @Override
+ public List<String> apply(String from) {
+ DatabagItem bootstrapConfig = bootstrapConfigForGroup.apply(from);
+ Map<String, JsonBall> config = json.fromJson(bootstrapConfig.toString(),
+ BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE);
+ JsonBall runlist = config.get("run_list");
+ return json.fromJson(runlist.toString(), RUN_LIST_TYPE);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/functions/UriForResource.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/functions/UriForResource.java b/apis/chef/src/main/java/org/jclouds/chef/functions/UriForResource.java
new file mode 100644
index 0000000..d5d0810
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/functions/UriForResource.java
@@ -0,0 +1,42 @@
+/*
+ * 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.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import javax.inject.Singleton;
+
+import org.jclouds.chef.domain.Resource;
+
+import com.google.common.base.Function;
+
+/**
+ * Extracts the uri field of the given {@link Resource}.
+ */
+@Singleton
+public class UriForResource implements Function<Object, URI> {
+
+ @Override
+ public URI apply(Object input) {
+ checkArgument(checkNotNull(input, "input") instanceof Resource,
+ "This function can only be applied to Resource objects");
+ return ((Resource) input).getUrl();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandler.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandler.java b/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandler.java
new file mode 100644
index 0000000..3b4da4a
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefApiErrorRetryHandler.java
@@ -0,0 +1,67 @@
+/*
+ * 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.handlers;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+import javax.annotation.Resource;
+import javax.inject.Named;
+
+import org.jclouds.Constants;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
+import org.jclouds.logging.Logger;
+
+import com.google.inject.Inject;
+
+/**
+ * Allow for eventual consistency on sandbox requests.
+ */
+public class ChefApiErrorRetryHandler implements HttpRetryHandler {
+
+ @Inject(optional = true)
+ @Named(Constants.PROPERTY_MAX_RETRIES)
+ private int retryCountLimit = 5;
+
+ @Resource
+ protected Logger logger = Logger.NULL;
+
+ private final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
+
+ @Inject
+ ChefApiErrorRetryHandler(BackoffLimitedRetryHandler backoffLimitedRetryHandler) {
+ this.backoffLimitedRetryHandler = backoffLimitedRetryHandler;
+ }
+
+ public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
+ if (command.getFailureCount() > retryCountLimit)
+ return false;
+ if (response.getStatusCode() == 400 && command.getCurrentRequest().getMethod().equals("PUT")
+ && command.getCurrentRequest().getEndpoint().getPath().indexOf("sandboxes") != -1) {
+ if (response.getPayload() != null) {
+ String error = new String(closeClientButKeepContentStream(response));
+ if (error != null && error.indexOf("was not uploaded") != -1) {
+ return backoffLimitedRetryHandler.shouldRetryRequest(command, response);
+ }
+ }
+ }
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefErrorHandler.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefErrorHandler.java b/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefErrorHandler.java
new file mode 100644
index 0000000..3376219
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/handlers/ChefErrorHandler.java
@@ -0,0 +1,81 @@
+/*
+ * 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.handlers;
+
+import static com.google.common.base.Throwables.propagate;
+
+import java.io.IOException;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.functions.ParseErrorFromJsonOrReturnBody;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.logging.Logger;
+import org.jclouds.rest.AuthorizationException;
+import org.jclouds.rest.ResourceNotFoundException;
+
+import com.google.common.io.Closeables;
+
+/**
+ * This will parse and set an appropriate exception on the command object.
+ */
+@Singleton
+public class ChefErrorHandler implements HttpErrorHandler {
+ @Resource
+ protected Logger logger = Logger.NULL;
+ private final ParseErrorFromJsonOrReturnBody errorParser;
+
+ @Inject
+ ChefErrorHandler(ParseErrorFromJsonOrReturnBody errorParser) {
+ this.errorParser = errorParser;
+ }
+
+ public void handleError(HttpCommand command, HttpResponse response) {
+ String message = errorParser.apply(response);
+ Exception exception = new HttpResponseException(command, response, message);
+ try {
+ message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
+ response.getStatusLine());
+ switch (response.getStatusCode()) {
+ case 401:
+ case 403:
+ exception = new AuthorizationException(message, exception);
+ break;
+ case 404:
+ if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
+ exception = new ResourceNotFoundException(message, exception);
+ }
+ break;
+ }
+ } finally {
+ if (response.getPayload() != null) {
+ try {
+ Closeables.close(response.getPayload().getInput(), true);
+ } catch (IOException e) {
+ throw propagate(e);
+ }
+ }
+ command.setException(exception);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/internal/BaseChefService.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/internal/BaseChefService.java b/apis/chef/src/main/java/org/jclouds/chef/internal/BaseChefService.java
new file mode 100644
index 0000000..d390555
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/internal/BaseChefService.java
@@ -0,0 +1,299 @@
+/*
+ * 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.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.chef.config.ChefProperties.CHEF_BOOTSTRAP_DATABAG;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.PrivateKey;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.ChefContext;
+import org.jclouds.chef.ChefService;
+import org.jclouds.chef.config.ChefProperties;
+import org.jclouds.chef.domain.BootstrapConfig;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.DatabagItem;
+import org.jclouds.chef.domain.Environment;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.functions.BootstrapConfigForGroup;
+import org.jclouds.chef.functions.GroupToBootScript;
+import org.jclouds.chef.functions.RunListForGroup;
+import org.jclouds.chef.strategy.CleanupStaleNodesAndClients;
+import org.jclouds.chef.strategy.CreateNodeAndPopulateAutomaticAttributes;
+import org.jclouds.chef.strategy.DeleteAllClientsInList;
+import org.jclouds.chef.strategy.DeleteAllNodesInList;
+import org.jclouds.chef.strategy.ListClients;
+import org.jclouds.chef.strategy.ListCookbookVersions;
+import org.jclouds.chef.strategy.ListCookbookVersionsInEnvironment;
+import org.jclouds.chef.strategy.ListEnvironments;
+import org.jclouds.chef.strategy.ListNodes;
+import org.jclouds.chef.strategy.ListNodesInEnvironment;
+import org.jclouds.chef.strategy.UpdateAutomaticAttributesOnNode;
+import org.jclouds.crypto.Crypto;
+import org.jclouds.domain.JsonBall;
+import org.jclouds.io.Payloads;
+import org.jclouds.io.payloads.RSADecryptingPayload;
+import org.jclouds.io.payloads.RSAEncryptingPayload;
+import org.jclouds.json.Json;
+import org.jclouds.logging.Logger;
+import org.jclouds.scriptbuilder.domain.Statement;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Maps;
+import com.google.common.io.ByteStreams;
+import com.google.common.io.InputSupplier;
+
+@Singleton
+public class BaseChefService implements ChefService {
+
+ private final ChefContext chefContext;
+ private final ChefApi api;
+ private final CleanupStaleNodesAndClients cleanupStaleNodesAndClients;
+ private final CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes;
+ private final DeleteAllNodesInList deleteAllNodesInList;
+ private final ListNodes listNodes;
+ private final DeleteAllClientsInList deleteAllClientsInList;
+ private final ListClients listClients;
+ private final UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode;
+ private final Supplier<PrivateKey> privateKey;
+ private final GroupToBootScript groupToBootScript;
+ private final String databag;
+ private final BootstrapConfigForGroup bootstrapConfigForGroup;
+ private final RunListForGroup runListForGroup;
+ private final ListCookbookVersions listCookbookVersions;
+ private final ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment;
+ private final ListEnvironments listEnvironments;
+ private final ListNodesInEnvironment listNodesInEnvironment;
+ private final Json json;
+ private final Crypto crypto;
+
+ @Resource
+ @Named(ChefProperties.CHEF_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ protected BaseChefService(ChefContext chefContext, ChefApi api,
+ CleanupStaleNodesAndClients cleanupStaleNodesAndClients,
+ CreateNodeAndPopulateAutomaticAttributes createNodeAndPopulateAutomaticAttributes,
+ DeleteAllNodesInList deleteAllNodesInList, ListNodes listNodes, DeleteAllClientsInList deleteAllClientsInList,
+ ListClients listClients, ListCookbookVersions listCookbookVersions,
+ UpdateAutomaticAttributesOnNode updateAutomaticAttributesOnNode, Supplier<PrivateKey> privateKey,
+ @Named(CHEF_BOOTSTRAP_DATABAG) String databag, GroupToBootScript groupToBootScript,
+ BootstrapConfigForGroup bootstrapConfigForGroup, RunListForGroup runListForGroup,
+ ListEnvironments listEnvironments, ListNodesInEnvironment listNodesInEnvironment,
+ ListCookbookVersionsInEnvironment listCookbookVersionsInEnvironment, Json json, Crypto crypto) {
+ this.chefContext = checkNotNull(chefContext, "chefContext");
+ this.api = checkNotNull(api, "api");
+ this.cleanupStaleNodesAndClients = checkNotNull(cleanupStaleNodesAndClients, "cleanupStaleNodesAndClients");
+ this.createNodeAndPopulateAutomaticAttributes = checkNotNull(createNodeAndPopulateAutomaticAttributes,
+ "createNodeAndPopulateAutomaticAttributes");
+ this.deleteAllNodesInList = checkNotNull(deleteAllNodesInList, "deleteAllNodesInList");
+ this.listNodes = checkNotNull(listNodes, "listNodes");
+ this.deleteAllClientsInList = checkNotNull(deleteAllClientsInList, "deleteAllClientsInList");
+ this.listClients = checkNotNull(listClients, "listClients");
+ this.listCookbookVersions = checkNotNull(listCookbookVersions, "listCookbookVersions");
+ this.updateAutomaticAttributesOnNode = checkNotNull(updateAutomaticAttributesOnNode,
+ "updateAutomaticAttributesOnNode");
+ this.privateKey = checkNotNull(privateKey, "privateKey");
+ this.groupToBootScript = checkNotNull(groupToBootScript, "groupToBootScript");
+ this.databag = checkNotNull(databag, "databag");
+ this.bootstrapConfigForGroup = checkNotNull(bootstrapConfigForGroup, "bootstrapConfigForGroup");
+ this.runListForGroup = checkNotNull(runListForGroup, "runListForGroup");
+ this.listEnvironments = checkNotNull(listEnvironments, "listEnvironments");
+ this.listNodesInEnvironment = checkNotNull(listNodesInEnvironment, "listNodesInEnvironment");
+ this.listCookbookVersionsInEnvironment = checkNotNull(listCookbookVersionsInEnvironment,"listCookbookVersionsInEnvironment");
+ this.json = checkNotNull(json, "json");
+ this.crypto = checkNotNull(crypto, "crypto");
+ }
+
+ @Override
+ public ChefContext getContext() {
+ return chefContext;
+ }
+
+ @Override
+ public byte[] encrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
+ return ByteStreams.toByteArray(new RSAEncryptingPayload(crypto, Payloads.newPayload(supplier.getInput()), privateKey
+ .get()));
+ }
+
+ @Override
+ public byte[] decrypt(InputSupplier<? extends InputStream> supplier) throws IOException {
+ return ByteStreams.toByteArray(new RSADecryptingPayload(crypto, Payloads.newPayload(supplier.getInput()), privateKey
+ .get()));
+ }
+
+ @VisibleForTesting
+ String buildBootstrapConfiguration(BootstrapConfig bootstrapConfig) {
+ checkNotNull(bootstrapConfig, "bootstrapConfig must not be null");
+
+ Map<String, Object> configMap = Maps.newHashMap();
+ configMap.put("run_list", bootstrapConfig.getRunList());
+
+ if (bootstrapConfig.getEnvironment().isPresent()) {
+ configMap.put("environment", bootstrapConfig.getEnvironment().get());
+ }
+
+ if (bootstrapConfig.getAttribtues().isPresent()) {
+ Map<String, Object> attributes = json.fromJson(bootstrapConfig.getAttribtues().get().toString(),
+ BootstrapConfigForGroup.BOOTSTRAP_CONFIG_TYPE);
+ configMap.putAll(attributes);
+ }
+
+ return json.toJson(configMap);
+ }
+
+ @Override
+ public Statement createBootstrapScriptForGroup(String group) {
+ return groupToBootScript.apply(group);
+ }
+
+ @Override
+ public void updateBootstrapConfigForGroup(String group, BootstrapConfig bootstrapConfig) {
+ try {
+ api.createDatabag(databag);
+ } catch (IllegalStateException e) {
+
+ }
+
+ String jsonConfig = buildBootstrapConfiguration(bootstrapConfig);
+ DatabagItem runlist = new DatabagItem(group, jsonConfig);
+
+ if (api.getDatabagItem(databag, group) == null) {
+ api.createDatabagItem(databag, runlist);
+ } else {
+ api.updateDatabagItem(databag, runlist);
+ }
+ }
+
+ @Override
+ public List<String> getRunListForGroup(String group) {
+ return runListForGroup.apply(group);
+ }
+
+ @Override
+ public JsonBall getBootstrapConfigForGroup(String group) {
+ return bootstrapConfigForGroup.apply(group);
+ }
+
+ @Override
+ public void cleanupStaleNodesAndClients(String prefix, int secondsStale) {
+ cleanupStaleNodesAndClients.execute(prefix, secondsStale);
+ }
+
+ @Override
+ public Node createNodeAndPopulateAutomaticAttributes(String nodeName, Iterable<String> runList) {
+ return createNodeAndPopulateAutomaticAttributes.execute(nodeName, runList);
+ }
+
+ @Override
+ public void updateAutomaticAttributesOnNode(String nodeName) {
+ updateAutomaticAttributesOnNode.execute(nodeName);
+ }
+
+ @Override
+ public void deleteAllNodesInList(Iterable<String> names) {
+ deleteAllNodesInList.execute(names);
+ }
+
+ @Override
+ public void deleteAllClientsInList(Iterable<String> names) {
+ deleteAllClientsInList.execute(names);
+ }
+
+ @Override
+ public Iterable<? extends Node> listNodes() {
+ return listNodes.execute();
+ }
+
+ @Override
+ public Iterable<? extends Node> listNodes(ExecutorService executorService) {
+ return listNodes.execute(executorService);
+ }
+
+ @Override
+ public Iterable<? extends Client> listClients() {
+ return listClients.execute();
+ }
+
+ @Override
+ public Iterable<? extends Client> listClients(ExecutorService executorService) {
+ return listClients.execute(executorService);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersions() {
+ return listCookbookVersions.execute();
+ }
+
+ @Override public Iterable<? extends CookbookVersion> listCookbookVersions(
+ ExecutorService executorService) {
+ return listCookbookVersions.execute(executorService);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName) {
+ return listCookbookVersionsInEnvironment.execute(environmentName);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
+ ExecutorService executorService) {
+ return listCookbookVersionsInEnvironment.execute(executorService, environmentName);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
+ String numVersions) {
+ return listCookbookVersionsInEnvironment.execute(environmentName, numVersions);
+ }
+
+ @Override
+ public Iterable<? extends CookbookVersion> listCookbookVersionsInEnvironment(String environmentName,
+ String numVersions, ExecutorService executorService) {
+ return listCookbookVersionsInEnvironment.execute(executorService, environmentName, numVersions);
+ }
+
+ @Override
+ public Iterable<? extends Environment> listEnvironments() {
+ return listEnvironments.execute();
+ }
+
+ @Override
+ public Iterable<? extends Node> listNodesInEnvironment(String environmentName) {
+ return listNodesInEnvironment.execute(environmentName);
+ }
+
+ @Override
+ public Iterable<? extends Node> listNodesInEnvironment(String environmentName, ExecutorService executorService) {
+ return listNodesInEnvironment.execute(executorService, environmentName);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/internal/ChefContextImpl.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/internal/ChefContextImpl.java b/apis/chef/src/main/java/org/jclouds/chef/internal/ChefContextImpl.java
new file mode 100644
index 0000000..8aef880
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/internal/ChefContextImpl.java
@@ -0,0 +1,55 @@
+/*
+ * 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.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.Context;
+import org.jclouds.chef.ChefContext;
+import org.jclouds.chef.ChefService;
+import org.jclouds.internal.BaseView;
+import org.jclouds.location.Provider;
+
+import com.google.common.reflect.TypeToken;
+
+@Singleton
+public class ChefContextImpl extends BaseView implements ChefContext {
+ private final ChefService chefService;
+
+ @Inject
+ protected ChefContextImpl(@Provider Context backend, @Provider TypeToken<? extends Context> backendType,
+ ChefService chefService) {
+ super(backend, backendType);
+ this.chefService = checkNotNull(chefService, "chefService");
+ }
+
+ @Override
+ public ChefService getChefService() {
+ return chefService;
+ }
+
+ @Override
+ public void close() throws IOException {
+ delegate().close();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/options/CreateClientOptions.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/options/CreateClientOptions.java b/apis/chef/src/main/java/org/jclouds/chef/options/CreateClientOptions.java
new file mode 100644
index 0000000..776d7bb
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/options/CreateClientOptions.java
@@ -0,0 +1,64 @@
+/*
+ * 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.options;
+
+/**
+ * Options for the create client method.
+ */
+public class CreateClientOptions implements Cloneable {
+ /** Administrator flag. This flag will be ignored in Opscode Hosted Chef. */
+ private boolean admin;
+
+ public CreateClientOptions() {
+ }
+
+ CreateClientOptions(final boolean admin) {
+ super();
+ this.admin = admin;
+ }
+
+ public boolean isAdmin() {
+ return admin;
+ }
+
+ public CreateClientOptions admin() {
+ this.admin = true;
+ return this;
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new CreateClientOptions(admin);
+ }
+
+ @Override
+ public String toString() {
+ return "[admin=" + admin + "]";
+ }
+
+ public static class Builder {
+ /**
+ * @see CreateClientOptions#admin()
+ */
+ public static CreateClientOptions admin() {
+ CreateClientOptions options = new CreateClientOptions();
+ return options.admin();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/options/SearchOptions.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/options/SearchOptions.java b/apis/chef/src/main/java/org/jclouds/chef/options/SearchOptions.java
new file mode 100644
index 0000000..cbc1d54
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/options/SearchOptions.java
@@ -0,0 +1,95 @@
+/*
+ * 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.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+/**
+ * Options for the search api.
+ */
+public class SearchOptions extends BaseHttpRequestOptions {
+
+ /**
+ * A valid search string.
+ */
+ public SearchOptions query(String query) {
+ this.queryParameters.put("q", checkNotNull(query, "query"));
+ return this;
+ }
+
+ /**
+ * A sort string, such as 'name DESC'.
+ */
+ public SearchOptions sort(String sort) {
+ this.queryParameters.put("sort", checkNotNull(sort, "sort"));
+ return this;
+ }
+
+ /**
+ * The number of rows to return.
+ */
+ public SearchOptions rows(int rows) {
+ this.queryParameters.put("rows", String.valueOf(rows));
+ return this;
+ }
+
+ /**
+ * The result number to start from.
+ */
+ public SearchOptions start(int start) {
+ this.queryParameters.put("start", String.valueOf(start));
+ return this;
+ }
+
+ public static class Builder {
+
+ /**
+ * @see SearchOptions#query(String)
+ */
+ public static SearchOptions query(String query) {
+ SearchOptions options = new SearchOptions();
+ return options.query(query);
+ }
+
+ /**
+ * @see SearchOptions#sort(String)
+ */
+ public static SearchOptions start(String start) {
+ SearchOptions options = new SearchOptions();
+ return options.sort(start);
+ }
+
+ /**
+ * @see SearchOptions#rows(int)
+ */
+ public static SearchOptions rows(int rows) {
+ SearchOptions options = new SearchOptions();
+ return options.rows(rows);
+ }
+
+ /**
+ * @see SearchOptions#start(int)
+ */
+ public static SearchOptions start(int start) {
+ SearchOptions options = new SearchOptions();
+ return options.start(start);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/predicates/CookbookVersionPredicates.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/predicates/CookbookVersionPredicates.java b/apis/chef/src/main/java/org/jclouds/chef/predicates/CookbookVersionPredicates.java
new file mode 100644
index 0000000..7edbcae
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/predicates/CookbookVersionPredicates.java
@@ -0,0 +1,93 @@
+/*
+ * 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.predicates;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.get;
+
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.domain.Resource;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.LinkedListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * Container for cookbook filters (predicates).
+ *
+ * This class has static methods that create customized predicates to use with
+ * {@link org.jclouds.chef.ChefService}.
+ */
+public class CookbookVersionPredicates {
+ /**
+ * @see #containsRecipes
+ */
+ public static Predicate<CookbookVersion> containsRecipe(String recipe) {
+ return containsRecipes(checkNotNull(recipe, "recipe must be defined"));
+ }
+
+ /**
+ * Note that the default recipe of a cookbook is its name. Otherwise, you
+ * prefix the recipe with the name of the cookbook. ex. {@code apache2} will
+ * be the default recipe where {@code apache2::mod_proxy} is a specific one
+ * in the cookbook.
+ *
+ * @param recipes
+ * names of the recipes.
+ * @return true if the cookbook version contains a recipe in the list.
+ */
+ public static Predicate<CookbookVersion> containsRecipes(String... recipes) {
+ checkNotNull(recipes, "recipes must be defined");
+ final Multimap<String, String> search = LinkedListMultimap.create();
+ for (String recipe : recipes) {
+ if (recipe.indexOf("::") != -1) {
+ Iterable<String> nameRecipe = Splitter.on("::").split(recipe);
+ search.put(get(nameRecipe, 0), get(nameRecipe, 1) + ".rb");
+ } else {
+ search.put(recipe, "default.rb");
+ }
+ }
+ return new Predicate<CookbookVersion>() {
+ @Override
+ public boolean apply(final CookbookVersion cookbookVersion) {
+ return search.containsKey(cookbookVersion.getCookbookName())
+ && any(search.get(cookbookVersion.getCookbookName()), new Predicate<String>() {
+
+ @Override
+ public boolean apply(final String recipeName) {
+ return any(cookbookVersion.getRecipes(), new Predicate<Resource>() {
+
+ @Override
+ public boolean apply(Resource resource) {
+ return resource.getName().equals(recipeName);
+ }
+
+ });
+ }
+
+ });
+ }
+
+ @Override
+ public String toString() {
+ return "containsRecipes(" + search + ")";
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/CleanupStaleNodesAndClients.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/CleanupStaleNodesAndClients.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/CleanupStaleNodesAndClients.java
new file mode 100644
index 0000000..8519450
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/CleanupStaleNodesAndClients.java
@@ -0,0 +1,32 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.strategy.internal.CleanupStaleNodesAndClientsImpl;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ *
+ * Cleans up nodes and clients who have been hanging around too long.
+ */
+@ImplementedBy(CleanupStaleNodesAndClientsImpl.class)
+public interface CleanupStaleNodesAndClients {
+
+ void execute(String prefix, int secondsStale);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/CreateNodeAndPopulateAutomaticAttributes.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/CreateNodeAndPopulateAutomaticAttributes.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/CreateNodeAndPopulateAutomaticAttributes.java
new file mode 100644
index 0000000..249be48
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/CreateNodeAndPopulateAutomaticAttributes.java
@@ -0,0 +1,33 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.strategy.internal.CreateNodeAndPopulateAutomaticAttributesImpl;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ *
+ * Creates a new node with automatic attributes.
+ */
+@ImplementedBy(CreateNodeAndPopulateAutomaticAttributesImpl.class)
+public interface CreateNodeAndPopulateAutomaticAttributes {
+ Node execute(Node node);
+
+ Node execute(String nodeName, Iterable<String> runList);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllClientsInList.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllClientsInList.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllClientsInList.java
new file mode 100644
index 0000000..7dd7b89
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllClientsInList.java
@@ -0,0 +1,34 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.strategy.internal.DeleteAllClientsInListImpl;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.ImplementedBy;
+
+/**
+ * Deletes all clients in a given list.
+ */
+@ImplementedBy(DeleteAllClientsInListImpl.class)
+public interface DeleteAllClientsInList {
+
+ void execute(Iterable<String> names);
+
+ void execute(ListeningExecutorService executor, Iterable<String> names);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllNodesInList.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllNodesInList.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllNodesInList.java
new file mode 100644
index 0000000..8867e49
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/DeleteAllNodesInList.java
@@ -0,0 +1,31 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.strategy.internal.DeleteAllNodesInListImpl;
+
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.ImplementedBy;
+
+@ImplementedBy(DeleteAllNodesInListImpl.class)
+public interface DeleteAllNodesInList {
+
+ void execute(Iterable<String> names);
+
+ void execute(ListeningExecutorService executor, Iterable<String> names);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListClients.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListClients.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListClients.java
new file mode 100644
index 0000000..aa40c2a
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListClients.java
@@ -0,0 +1,32 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.Client;
+import org.jclouds.chef.strategy.internal.ListClientsImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListClientsImpl.class)
+public interface ListClients {
+
+ Iterable<? extends Client> execute();
+
+ Iterable<? extends Client> execute(ExecutorService executor);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersions.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersions.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersions.java
new file mode 100644
index 0000000..45663a3
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersions.java
@@ -0,0 +1,32 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.strategy.internal.ListCookbookVersionsImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListCookbookVersionsImpl.class)
+public interface ListCookbookVersions {
+
+ Iterable<? extends CookbookVersion> execute();
+
+ Iterable<? extends CookbookVersion> execute(ExecutorService executor);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
new file mode 100644
index 0000000..188d29f
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListCookbookVersionsInEnvironment.java
@@ -0,0 +1,37 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.chef.strategy.internal.ListCookbookVersionsInEnvironmentImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListCookbookVersionsInEnvironmentImpl.class)
+public interface ListCookbookVersionsInEnvironment {
+
+ Iterable<? extends CookbookVersion> execute(String environmentName);
+
+ Iterable<? extends CookbookVersion> execute(String environmentName, String numVersions);
+
+ Iterable<? extends CookbookVersion> execute(ExecutorService executor, String environmentName);
+
+ Iterable<? extends CookbookVersion> execute(ExecutorService executor, String environmentName, String numVersions);
+
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListEnvironments.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListEnvironments.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListEnvironments.java
new file mode 100644
index 0000000..553e8d4
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListEnvironments.java
@@ -0,0 +1,31 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.Environment;
+import org.jclouds.chef.strategy.internal.ListEnvironmentsImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListEnvironmentsImpl.class)
+public interface ListEnvironments {
+
+ Iterable<? extends Environment> execute();
+
+ Iterable<? extends Environment> execute(ExecutorService executor);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodes.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodes.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodes.java
new file mode 100644
index 0000000..660eed0
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodes.java
@@ -0,0 +1,32 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.strategy.internal.ListNodesImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListNodesImpl.class)
+public interface ListNodes {
+
+ Iterable<? extends Node> execute();
+
+ Iterable<? extends Node> execute(ExecutorService executor);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodesInEnvironment.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodesInEnvironment.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodesInEnvironment.java
new file mode 100644
index 0000000..efeffe6
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/ListNodesInEnvironment.java
@@ -0,0 +1,32 @@
+/*
+ * 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.strategy;
+
+import com.google.inject.ImplementedBy;
+import org.jclouds.chef.domain.Node;
+import org.jclouds.chef.strategy.internal.ListNodesInEnvironmentImpl;
+
+import java.util.concurrent.ExecutorService;
+
+@ImplementedBy(ListNodesInEnvironmentImpl.class)
+public interface ListNodesInEnvironment {
+
+ Iterable<? extends Node> execute(String environmentName);
+
+ Iterable<? extends Node> execute(ExecutorService executor, String environmentName);
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/UpdateAutomaticAttributesOnNode.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/UpdateAutomaticAttributesOnNode.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/UpdateAutomaticAttributesOnNode.java
new file mode 100644
index 0000000..0dcb81e
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/UpdateAutomaticAttributesOnNode.java
@@ -0,0 +1,31 @@
+/*
+ * 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.strategy;
+
+import org.jclouds.chef.strategy.internal.UpdateAutomaticAttributesOnNodeImpl;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ *
+ * Updates node with new automatic attributes.
+ */
+@ImplementedBy(UpdateAutomaticAttributesOnNodeImpl.class)
+public interface UpdateAutomaticAttributesOnNode {
+
+ void execute(String nodeName);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/867c7a40/apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListCookbookVersionsImpl.java
----------------------------------------------------------------------
diff --git a/apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListCookbookVersionsImpl.java b/apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListCookbookVersionsImpl.java
new file mode 100644
index 0000000..94cf79a
--- /dev/null
+++ b/apis/chef/src/main/java/org/jclouds/chef/strategy/internal/BaseListCookbookVersionsImpl.java
@@ -0,0 +1,97 @@
+/*
+ * 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.strategy.internal;
+
+import com.google.common.base.Function;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.jclouds.chef.ChefApi;
+import org.jclouds.chef.domain.CookbookVersion;
+import org.jclouds.logging.Logger;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.util.concurrent.Futures.allAsList;
+import static com.google.common.util.concurrent.Futures.getUnchecked;
+
+public abstract class BaseListCookbookVersionsImpl {
+
+ protected final ChefApi api;
+
+ protected Logger logger = Logger.NULL;
+
+ BaseListCookbookVersionsImpl(ChefApi api) {
+ this.api = checkNotNull(api, "api");
+ }
+
+ protected Iterable<? extends CookbookVersion> execute(Iterable<String> toGet) {
+ return concat(transform(toGet, new Function<String, Iterable<? extends CookbookVersion>>() {
+
+ @Override
+ public Iterable<? extends CookbookVersion> apply(final String cookbook) {
+ // TODO getting each version could also go parallel
+ Set<String> cookbookVersions = api.listVersionsOfCookbook(cookbook);
+ Iterable<? extends CookbookVersion> cookbooksVersions = transform(cookbookVersions,
+ new Function<String, CookbookVersion>() {
+ @Override
+ public CookbookVersion apply(final String version) {
+ return api.getCookbook(cookbook, version);
+ }
+ }
+ );
+
+ logger.trace(String.format("getting versions of cookbook: %s", cookbook));
+ return cookbooksVersions;
+ }
+ }));
+
+ }
+
+ protected Iterable<? extends CookbookVersion> executeConcurrently(final ListeningExecutorService executor,
+ Iterable<String> cookbookNames) {
+ return concat(transform(cookbookNames, new Function<String, Iterable<? extends CookbookVersion>>() {
+
+ @Override
+ public Iterable<? extends CookbookVersion> apply(final String cookbook) {
+ // TODO getting each version could also go parallel
+ Set<String> cookbookVersions = api.listVersionsOfCookbook(cookbook);
+ ListenableFuture<List<CookbookVersion>> futures = allAsList(transform(cookbookVersions,
+ new Function<String, ListenableFuture<CookbookVersion>>() {
+ @Override
+ public ListenableFuture<CookbookVersion> apply(final String version) {
+ return executor.submit(new Callable<CookbookVersion>() {
+ @Override
+ public CookbookVersion call() throws Exception {
+ return api.getCookbook(cookbook, version);
+ }
+ });
+ }
+ }
+ ));
+
+ logger.trace(String.format("getting versions of cookbook: %s", cookbook));
+ return getUnchecked(futures);
+ }
+ }));
+ }
+
+}