github.com/noxiouz/docker@v0.7.3-0.20160629055221-3d231c78e8c5/daemon/cluster/convert/swarm.go (about)

     1  package convert
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"golang.org/x/crypto/bcrypt"
     9  
    10  	types "github.com/docker/engine-api/types/swarm"
    11  	swarmapi "github.com/docker/swarmkit/api"
    12  	"github.com/docker/swarmkit/protobuf/ptypes"
    13  )
    14  
    15  // SwarmFromGRPC converts a grpc Cluster to a Swarm.
    16  func SwarmFromGRPC(c swarmapi.Cluster) types.Swarm {
    17  	swarm := types.Swarm{
    18  		ID: c.ID,
    19  		Spec: types.Spec{
    20  			Orchestration: types.OrchestrationConfig{
    21  				TaskHistoryRetentionLimit: c.Spec.Orchestration.TaskHistoryRetentionLimit,
    22  			},
    23  			Raft: types.RaftConfig{
    24  				SnapshotInterval:           c.Spec.Raft.SnapshotInterval,
    25  				KeepOldSnapshots:           c.Spec.Raft.KeepOldSnapshots,
    26  				LogEntriesForSlowFollowers: c.Spec.Raft.LogEntriesForSlowFollowers,
    27  				HeartbeatTick:              c.Spec.Raft.HeartbeatTick,
    28  				ElectionTick:               c.Spec.Raft.ElectionTick,
    29  			},
    30  		},
    31  	}
    32  
    33  	heartbeatPeriod, _ := ptypes.Duration(c.Spec.Dispatcher.HeartbeatPeriod)
    34  	swarm.Spec.Dispatcher.HeartbeatPeriod = uint64(heartbeatPeriod)
    35  
    36  	swarm.Spec.CAConfig.NodeCertExpiry, _ = ptypes.Duration(c.Spec.CAConfig.NodeCertExpiry)
    37  
    38  	// Meta
    39  	swarm.Version.Index = c.Meta.Version.Index
    40  	swarm.CreatedAt, _ = ptypes.Timestamp(c.Meta.CreatedAt)
    41  	swarm.UpdatedAt, _ = ptypes.Timestamp(c.Meta.UpdatedAt)
    42  
    43  	// Annotations
    44  	swarm.Spec.Name = c.Spec.Annotations.Name
    45  	swarm.Spec.Labels = c.Spec.Annotations.Labels
    46  
    47  	for _, policy := range c.Spec.AcceptancePolicy.Policies {
    48  		p := types.Policy{
    49  			Role:       types.NodeRole(strings.ToLower(policy.Role.String())),
    50  			Autoaccept: policy.Autoaccept,
    51  		}
    52  		if policy.Secret != nil {
    53  			secret := string(policy.Secret.Data)
    54  			p.Secret = &secret
    55  		}
    56  		swarm.Spec.AcceptancePolicy.Policies = append(swarm.Spec.AcceptancePolicy.Policies, p)
    57  	}
    58  
    59  	return swarm
    60  }
    61  
    62  // SwarmSpecToGRPCandMerge converts a Spec to a grpc ClusterSpec and merge AcceptancePolicy from an existing grpc ClusterSpec if provided.
    63  func SwarmSpecToGRPCandMerge(s types.Spec, existingSpec *swarmapi.ClusterSpec) (swarmapi.ClusterSpec, error) {
    64  	spec := swarmapi.ClusterSpec{
    65  		Annotations: swarmapi.Annotations{
    66  			Name:   s.Name,
    67  			Labels: s.Labels,
    68  		},
    69  		Orchestration: swarmapi.OrchestrationConfig{
    70  			TaskHistoryRetentionLimit: s.Orchestration.TaskHistoryRetentionLimit,
    71  		},
    72  		Raft: swarmapi.RaftConfig{
    73  			SnapshotInterval:           s.Raft.SnapshotInterval,
    74  			KeepOldSnapshots:           s.Raft.KeepOldSnapshots,
    75  			LogEntriesForSlowFollowers: s.Raft.LogEntriesForSlowFollowers,
    76  			HeartbeatTick:              s.Raft.HeartbeatTick,
    77  			ElectionTick:               s.Raft.ElectionTick,
    78  		},
    79  		Dispatcher: swarmapi.DispatcherConfig{
    80  			HeartbeatPeriod: ptypes.DurationProto(time.Duration(s.Dispatcher.HeartbeatPeriod)),
    81  		},
    82  		CAConfig: swarmapi.CAConfig{
    83  			NodeCertExpiry: ptypes.DurationProto(s.CAConfig.NodeCertExpiry),
    84  		},
    85  	}
    86  
    87  	if err := SwarmSpecUpdateAcceptancePolicy(&spec, s.AcceptancePolicy, existingSpec); err != nil {
    88  		return swarmapi.ClusterSpec{}, err
    89  	}
    90  
    91  	return spec, nil
    92  }
    93  
    94  // SwarmSpecUpdateAcceptancePolicy updates a grpc ClusterSpec using AcceptancePolicy.
    95  func SwarmSpecUpdateAcceptancePolicy(spec *swarmapi.ClusterSpec, acceptancePolicy types.AcceptancePolicy, oldSpec *swarmapi.ClusterSpec) error {
    96  	spec.AcceptancePolicy.Policies = nil
    97  	hashs := make(map[string][]byte)
    98  
    99  	for _, p := range acceptancePolicy.Policies {
   100  		role, ok := swarmapi.NodeRole_value[strings.ToUpper(string(p.Role))]
   101  		if !ok {
   102  			return fmt.Errorf("invalid Role: %q", p.Role)
   103  		}
   104  
   105  		policy := &swarmapi.AcceptancePolicy_RoleAdmissionPolicy{
   106  			Role:       swarmapi.NodeRole(role),
   107  			Autoaccept: p.Autoaccept,
   108  		}
   109  
   110  		if p.Secret != nil {
   111  			if *p.Secret == "" { // if provided secret is empty, it means erase previous secret.
   112  				policy.Secret = nil
   113  			} else { // if provided secret is not empty, we generate a new one.
   114  				hashPwd, ok := hashs[*p.Secret]
   115  				if !ok {
   116  					hashPwd, _ = bcrypt.GenerateFromPassword([]byte(*p.Secret), 0)
   117  					hashs[*p.Secret] = hashPwd
   118  				}
   119  				policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
   120  					Data: hashPwd,
   121  					Alg:  "bcrypt",
   122  				}
   123  			}
   124  		} else if oldSecret := getOldSecret(oldSpec, policy.Role); oldSecret != nil { // else use the old one.
   125  			policy.Secret = &swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret{
   126  				Data: oldSecret.Data,
   127  				Alg:  oldSecret.Alg,
   128  			}
   129  		}
   130  
   131  		spec.AcceptancePolicy.Policies = append(spec.AcceptancePolicy.Policies, policy)
   132  	}
   133  	return nil
   134  }
   135  
   136  func getOldSecret(oldSpec *swarmapi.ClusterSpec, role swarmapi.NodeRole) *swarmapi.AcceptancePolicy_RoleAdmissionPolicy_HashedSecret {
   137  	if oldSpec == nil {
   138  		return nil
   139  	}
   140  	for _, p := range oldSpec.AcceptancePolicy.Policies {
   141  		if p.Role == role {
   142  			return p.Secret
   143  		}
   144  	}
   145  	return nil
   146  }