/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * Licensed 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.rundeck.plugin.example;

import com.dtolabs.rundeck.core.common.INodeEntry;
import com.dtolabs.rundeck.core.execution.workflow.StepExecutionContext;
import com.dtolabs.rundeck.core.plugins.Plugin;
import com.dtolabs.rundeck.plugins.ServiceNameConstants;
import com.dtolabs.rundeck.plugins.descriptions.PluginDescription;
import com.dtolabs.rundeck.plugins.descriptions.PluginProperty;
import com.dtolabs.rundeck.plugins.orchestrator.Orchestrator;
import com.dtolabs.rundeck.plugins.orchestrator.OrchestratorPlugin;

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

@Plugin(name = "subset", service = ServiceNameConstants.Orchestrator)
@PluginDescription(title = "Random Subset", description = "Chooses only a random subset of the target nodes.")
public class RandomSubsetOrchestratorPlugin implements OrchestratorPlugin {


    @PluginProperty(title = "Count", description = "Number of nodes to select from the pool", defaultValue = "1")
    protected int count;

    @Override
    public Orchestrator createOrchestrator(StepExecutionContext context, Collection<INodeEntry> nodes) {
        String ident = createWFLayerIdent(context);
        //use the ident as random seed to allow repeatable sequence of random nodes
        //if this orchestrator config is invoked more than once in the same
        //workflow layer
        return new RandomSubsetOrchestrator(count, context, nodes, (long) ident.hashCode());
    }

    public String createWFLayerIdent(final StepExecutionContext context) {
        //create a string which identifies this execution layer uniquely
        List<Integer> stepContext = context.getStepContext();
        String ident = context.getFrameworkProject();
        if (context.getDataContext().get("job") != null && context.getDataContext().get("job").get("execid") != null) {
            ident += context.getDataContext().get("job").get("execid");
        }

        return ident +
               String.join(",", stepContext.stream().map(Object::toString).collect(Collectors.toList()));
    }
}

@@ -1148,16 +1148,172 @@
 lugin;%0A%0A
+import java.io.UnsupportedEncodingException;%0Aimport java.nio.ByteBuffer;%0Aimport java.security.MessageDigest;%0Aimport java.security.NoSuchAlgorithmException;%0A
 import j
@@ -2219,14 +2219,637 @@
 es, 
-(long)
+genSeed(ident));%0A    %7D%0A%0A    /**%0A     * generate random seed from unique ident string%0A     * @param ident%0A     * @return seed long%0A     */%0A    public static long genSeed(final String ident) %7B%0A        try %7B%0A            MessageDigest instance = MessageDigest.getInstance(%22SHA-1%22);%0A            byte%5B%5D strbytes = ident.getBytes(%22UTF-8%22);%0A            byte%5B%5D digest = instance.digest(strbytes);%0A%0A            //use first 8 bytes as a long%0A            return ByteBuffer.wrap(digest, 0, Long.BYTES).getLong();%0A        %7D catch (NoSuchAlgorithmException %7C UnsupportedEncodingException e) %7B%0A            //not random looking%0A            return
  ide
@@ -2861,24 +2861,34 @@
 shCode()
-)
 ;%0A    
+  
-%7D
+  %7D%0A    %7D%0A
 %0A%0A    pu

Fix #3312 improve the reproducible seed generation