<commit_before>//
// Copyright 2017, Sander van Harmelen
//
// 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 gitlab

import (
	"fmt"
)

// GroupMembersService handles communication with the group members
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html
type GroupMembersService struct {
	client *Client
}

// GroupMemberSAMLIdentity represents the SAML Identity link for the group member.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
// Gitlab MR for API change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20357
// Gitlab MR for API Doc change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25652
type GroupMemberSAMLIdentity struct {
	ExternUID      string `json:"extern_uid"`
	Provider       string `json:"provider"`
	SAMLProviderID int    `json:"saml_provider_id"`
}

// GroupMember represents a GitLab group member.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html
type GroupMember struct {
	ID                int                      `json:"id"`
	Username          string                   `json:"username"`
	Name              string                   `json:"name"`
	State             string                   `json:"state"`
	AvatarURL         string                   `json:"avatar_url"`
	WebURL            string                   `json:"web_url"`
	ExpiresAt         *ISOTime                 `json:"expires_at"`
	AccessLevel       AccessLevelValue         `json:"access_level"`
	GroupSAMLIdentity *GroupMemberSAMLIdentity `json:"group_saml_identity"`
}

// ListGroupMembersOptions represents the available ListGroupMembers() and
// ListAllGroupMembers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
type ListGroupMembersOptions struct {
	ListOptions
	Query *string `url:"query,omitempty" json:"query,omitempty"`
}

// ListGroupMembers get a list of group members viewable by the authenticated
// user. Inherited members through ancestor groups are not included.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
func (s *GroupsService) ListGroupMembers(gid interface{}, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var gm []*GroupMember
	resp, err := s.client.Do(req, &gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// ListAllGroupMembers get a list of group members viewable by the authenticated
// user. Returns a list including inherited members through ancestor groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project-including-inherited-members
func (s *GroupsService) ListAllGroupMembers(gid interface{}, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/all", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var gm []*GroupMember
	resp, err := s.client.Do(req, &gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// AddGroupMemberOptions represents the available AddGroupMember() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project
type AddGroupMemberOptions struct {
	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
	ExpiresAt   *string           `url:"expires_at,omitempty" json:"expires_at"`
}

// GetGroupMember gets a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#get-a-member-of-a-group-or-project
func (s *GroupMembersService) GetGroupMember(gid interface{}, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// AddGroupMember adds a user to the list of group members.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project
func (s *GroupMembersService) AddGroupMember(gid interface{}, opt *AddGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// ShareWithGroup shares a group with the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/groups.html#share-groups-with-groups
func (s *GroupMembersService) ShareWithGroup(gid interface{}, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/share", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	g := new(Group)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// RemoveShareWithGroup allows to unshare a group from a group.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/groups.html#delete-link-sharing-group-with-another-group
func (s *GroupMembersService) RemoveShareWithGroup(gid interface{}, groupID int, options ...RequestOptionFunc) (*Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/share/%d", pathEscape(group), groupID)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}

// EditGroupMemberOptions represents the available EditGroupMember()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project
type EditGroupMemberOptions struct {
	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
	ExpiresAt   *string           `url:"expires_at,omitempty" json:"expires_at"`
}

// EditGroupMember updates a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project
func (s *GroupMembersService) EditGroupMember(gid interface{}, user int, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// RemoveGroupMember removes user from user team.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#remove-a-member-from-a-group-or-project
func (s *GroupMembersService) RemoveGroupMember(gid interface{}, user int, options ...RequestOptionFunc) (*Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<commit_msg>Update group_members delete group API link<commit_after>//
// Copyright 2017, Sander van Harmelen
//
// 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 gitlab

import (
	"fmt"
)

// GroupMembersService handles communication with the group members
// related methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html
type GroupMembersService struct {
	client *Client
}

// GroupMemberSAMLIdentity represents the SAML Identity link for the group member.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
// Gitlab MR for API change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20357
// Gitlab MR for API Doc change: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25652
type GroupMemberSAMLIdentity struct {
	ExternUID      string `json:"extern_uid"`
	Provider       string `json:"provider"`
	SAMLProviderID int    `json:"saml_provider_id"`
}

// GroupMember represents a GitLab group member.
//
// GitLab API docs: https://docs.gitlab.com/ce/api/members.html
type GroupMember struct {
	ID                int                      `json:"id"`
	Username          string                   `json:"username"`
	Name              string                   `json:"name"`
	State             string                   `json:"state"`
	AvatarURL         string                   `json:"avatar_url"`
	WebURL            string                   `json:"web_url"`
	ExpiresAt         *ISOTime                 `json:"expires_at"`
	AccessLevel       AccessLevelValue         `json:"access_level"`
	GroupSAMLIdentity *GroupMemberSAMLIdentity `json:"group_saml_identity"`
}

// ListGroupMembersOptions represents the available ListGroupMembers() and
// ListAllGroupMembers() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
type ListGroupMembersOptions struct {
	ListOptions
	Query *string `url:"query,omitempty" json:"query,omitempty"`
}

// ListGroupMembers get a list of group members viewable by the authenticated
// user. Inherited members through ancestor groups are not included.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project
func (s *GroupsService) ListGroupMembers(gid interface{}, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var gm []*GroupMember
	resp, err := s.client.Do(req, &gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// ListAllGroupMembers get a list of group members viewable by the authenticated
// user. Returns a list including inherited members through ancestor groups.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#list-all-members-of-a-group-or-project-including-inherited-members
func (s *GroupsService) ListAllGroupMembers(gid interface{}, opt *ListGroupMembersOptions, options ...RequestOptionFunc) ([]*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/all", pathEscape(group))

	req, err := s.client.NewRequest("GET", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	var gm []*GroupMember
	resp, err := s.client.Do(req, &gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// AddGroupMemberOptions represents the available AddGroupMember() options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project
type AddGroupMemberOptions struct {
	UserID      *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
	ExpiresAt   *string           `url:"expires_at,omitempty" json:"expires_at"`
}

// GetGroupMember gets a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#get-a-member-of-a-group-or-project
func (s *GroupMembersService) GetGroupMember(gid interface{}, user int, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("GET", u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// AddGroupMember adds a user to the list of group members.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#add-a-member-to-a-group-or-project
func (s *GroupMembersService) AddGroupMember(gid interface{}, opt *AddGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// ShareWithGroup shares a group with the group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/groups.html#share-groups-with-groups
func (s *GroupMembersService) ShareWithGroup(gid interface{}, opt *ShareWithGroupOptions, options ...RequestOptionFunc) (*Group, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/share", pathEscape(group))

	req, err := s.client.NewRequest("POST", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	g := new(Group)
	resp, err := s.client.Do(req, g)
	if err != nil {
		return nil, resp, err
	}

	return g, resp, err
}

// RemoveShareWithGroup allows to unshare a group from a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/groups.html#delete-link-sharing-group-with-another-group
func (s *GroupMembersService) RemoveShareWithGroup(gid interface{}, groupID int, options ...RequestOptionFunc) (*Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/share/%d", pathEscape(group), groupID)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}

// EditGroupMemberOptions represents the available EditGroupMember()
// options.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project
type EditGroupMemberOptions struct {
	AccessLevel *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
	ExpiresAt   *string           `url:"expires_at,omitempty" json:"expires_at"`
}

// EditGroupMember updates a member of a group.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#edit-a-member-of-a-group-or-project
func (s *GroupMembersService) EditGroupMember(gid interface{}, user int, opt *EditGroupMemberOptions, options ...RequestOptionFunc) (*GroupMember, *Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("PUT", u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	gm := new(GroupMember)
	resp, err := s.client.Do(req, gm)
	if err != nil {
		return nil, resp, err
	}

	return gm, resp, err
}

// RemoveGroupMember removes user from user team.
//
// GitLab API docs:
// https://docs.gitlab.com/ce/api/members.html#remove-a-member-from-a-group-or-project
func (s *GroupMembersService) RemoveGroupMember(gid interface{}, user int, options ...RequestOptionFunc) (*Response, error) {
	group, err := parseID(gid)
	if err != nil {
		return nil, err
	}
	u := fmt.Sprintf("groups/%s/members/%d", pathEscape(group), user)

	req, err := s.client.NewRequest("DELETE", u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.83"
<commit_msg>functions: 0.3.84 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.84"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.80"
<commit_msg>functions: 0.3.81 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.81"
<|endoftext|>


<commit_before>package version

// Version of Functions
var Version = "0.3.32"
<commit_msg>functions: 0.3.33 release [skip ci]<commit_after>package version

// Version of Functions
var Version = "0.3.33"
<|endoftext|>


<commit_before>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"text/template"

	"github.com/gorilla/mux"
	. "github.com/weaveworks/weave/common"
	"github.com/weaveworks/weave/ipam"
	"github.com/weaveworks/weave/mesh"
	"github.com/weaveworks/weave/nameserver"
	"github.com/weaveworks/weave/net/address"
	weave "github.com/weaveworks/weave/router"
)

var rootTemplate = template.New("root").Funcs(map[string]interface{}{
	"countDNSEntries": func(entries []nameserver.EntryStatus) int {
		count := 0
		for _, entry := range entries {
			if entry.Tombstone == 0 {
				count++
			}
		}
		return count
	},
	"upstreamServers": func(servers []string) string {
		if len(servers) == 0 {
			return "none"
		}
		return strings.Join(servers, ", ")
	},
	"printIPAMRanges": func(status ipam.Status) string {
		var buffer bytes.Buffer

		type stats struct {
			Ranges    []address.Range
			Addresses []address.Address
			Reachable bool
		}

		peerStats := make(map[mesh.PeerName]*stats)
		getOrCreateStats := func(peer mesh.PeerName) *stats {
			s, found := peerStats[peer]
			if !found {
				s = &stats{Reachable: status.IsKnownPeer(peer)}
				peerStats[peer] = s
			}
			return s
		}

		for _, entry := range status.Ring.Entries {
			stats := getOrCreateStats(entry.Peer)
			stats.Addresses = append(stats.Addresses, entry.Token)
		}

		for peer, ranges := range status.Ring.OwnedRangesByPeer() {
			stats := getOrCreateStats(peer)
			stats.Ranges = append(stats.Ranges, ranges...)
		}

		appendAddresses := func(peer mesh.PeerName, nickName string, reachable bool, addresses []address.Address, ranges []address.Range) {
			reachableStr := ""
			if !reachable {
				reachableStr = "- unreachable!"
			}
			ipsInRange := 0
			for _, chunk := range ranges {
				ipsInRange += int(chunk.Size())
			}
			percentageRanges := float32(ipsInRange) * 100.0 / float32(status.RangeNumIPs)

			displayName := peer.String() + "(" + nickName + ")"
			fmt.Fprintf(&buffer, "%20s: %8d IPs (%04.1f%% of total) - used: %d %s\n",
				displayName, ipsInRange, percentageRanges, len(addresses), reachableStr)
		}

		// print the local addresses
		if ourStats := peerStats[status.OurName]; ourStats != nil {
			appendAddresses(status.OurName, "local", true, ourStats.Addresses, ourStats.Ranges)
		}

		// and then the rest
		for peer, stats := range peerStats {
			if peer != status.OurName {
				nickname, found := status.Nicknames[peer]
				if !found {
					nickname = peer.String()
				}
				appendAddresses(peer, nickname, stats.Reachable, stats.Addresses, stats.Ranges)
			}
		}

		return buffer.String()
	},
	"printConnectionCounts": func(conns []mesh.LocalConnectionStatus) string {
		counts := make(map[string]int)
		for _, conn := range conns {
			counts[conn.State]++
		}
		return printCounts(counts, []string{"established", "pending", "retrying", "failed", "connecting"})
	},
	"printPeerConnectionCounts": func(peers []mesh.PeerStatus) string {
		counts := make(map[string]int)
		for _, peer := range peers {
			for _, conn := range peer.Connections {
				if conn.Established {
					counts["established"]++
				} else {
					counts["pending"]++
				}
			}
		}
		return printCounts(counts, []string{"established", "pending"})
	},
	"printState": func(enabled bool) string {
		if enabled {
			return "enabled"
		}
		return "disabled"
	},
	"trimSuffix": strings.TrimSuffix,
})

// Print counts in a specified order
func printCounts(counts map[string]int, keys []string) string {
	var stringCounts []string
	for _, key := range keys {
		if count, ok := counts[key]; ok {
			stringCounts = append(stringCounts, fmt.Sprintf("%d %s", count, key))
		}
	}
	return strings.Join(stringCounts, ", ")
}

// Strip escaped newlines from template
func escape(template string) string {
	return strings.Replace(template, "\\\n", "", -1)
}

// Define a named template panicking on error
func defTemplate(name string, text string) *template.Template {
	return template.Must(rootTemplate.New(name).Parse(escape(text)))
}

var statusTemplate = defTemplate("status", `\
       Version: {{.Version}}

       Service: router
      Protocol: {{.Router.Protocol}} \
{{if eq .Router.ProtocolMinVersion .Router.ProtocolMaxVersion}}\
{{.Router.ProtocolMaxVersion}}\
{{else}}\
{{.Router.ProtocolMinVersion}}..{{.Router.ProtocolMaxVersion}}\
{{end}}
          Name: {{.Router.Name}}({{.Router.NickName}})
    Encryption: {{printState .Router.Encryption}}
 PeerDiscovery: {{printState .Router.PeerDiscovery}}
       Targets: {{len .Router.Targets}}
   Connections: {{len .Router.Connections}}{{with printConnectionCounts .Router.Connections}} ({{.}}){{end}}
         Peers: {{len .Router.Peers}}{{with printPeerConnectionCounts .Router.Peers}} (with {{.}} connections){{end}}
{{if .IPAM}}\

       Service: ipam
{{if .IPAM.Entries}}\
     Consensus: achieved
{{else if .IPAM.Paxos}}\
     Consensus: waiting (quorum: {{.IPAM.Paxos.Quorum}}, known: {{.IPAM.Paxos.KnownNodes}})
{{else}}\
     Consensus: deferred
{{end}}\
         Range: {{.IPAM.Range}}
 DefaultSubnet: {{.IPAM.DefaultSubnet}}
{{end}}\
{{if .DNS}}\

       Service: dns
        Domain: {{.DNS.Domain}}
      Upstream: {{upstreamServers .DNS.Upstream}}
           TTL: {{.DNS.TTL}}
       Entries: {{countDNSEntries .DNS.Entries}}
{{end}}\
`)

var targetsTemplate = defTemplate("targetsTemplate", `\
{{range .Router.Targets}}{{.}}
{{end}}\
`)

var connectionsTemplate = defTemplate("connectionsTemplate", `\
{{range .Router.Connections}}\
{{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} {{printf "%-11v" .State}} {{.Info}}
{{end}}\
`)

var peersTemplate = defTemplate("peers", `\
{{range .Router.Peers}}\
{{.Name}}({{.NickName}})
{{range .Connections}}\
   {{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} \
{{$nameNickName := printf "%v(%v)" .Name .NickName}}{{printf "%-32v" $nameNickName}} \
{{if .Established}}established{{else}}pending{{end}}
{{end}}\
{{end}}\
`)

var dnsEntriesTemplate = defTemplate("dnsEntries", `\
{{$domain := printf ".%v" .DNS.Domain}}\
{{range .DNS.Entries}}\
{{if eq .Tombstone 0}}\
{{$hostname := trimSuffix .Hostname $domain}}\
{{printf "%-12v" $hostname}} {{printf "%-15v" .Address}} {{printf "%12.12v" .ContainerID}} {{.Origin}}
{{end}}\
{{end}}\
`)

var ipamTemplate = defTemplate("ipamTemplate", `{{printIPAMRanges .IPAM}}`)

type WeaveStatus struct {
	Version string
	Router  *weave.NetworkRouterStatus `json:"Router,omitempty"`
	IPAM    *ipam.Status               `json:"IPAM,omitempty"`
	DNS     *nameserver.Status         `json:"DNS,omitempty"`
}

func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) {
	status := func() WeaveStatus {
		return WeaveStatus{
			version,
			weave.NewNetworkRouterStatus(router),
			ipam.NewStatus(allocator, defaultSubnet),
			nameserver.NewStatus(ns, dnsserver)}
	}
	muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			json, err := json.MarshalIndent(status(), "", "    ")
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				Log.Error("Error during report marshalling: ", err)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(json)
		})

	muxRouter.Methods("GET").Path("/report").Queries("format", "{format}").HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			formatTemplate, err := template.New("format").Parse(mux.Vars(r)["format"])
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			if err := formatTemplate.Execute(w, status()); err != nil {
				http.Error(w, "error during template execution", http.StatusInternalServerError)
				Log.Error(err)
			}
		})

	defHandler := func(path string, template *template.Template) {
		muxRouter.Methods("GET").Path(path).HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				if err := template.Execute(w, status()); err != nil {
					http.Error(w, "error during template execution", http.StatusInternalServerError)
					Log.Error(err)
				}
			})
	}

	defHandler("/status", statusTemplate)
	defHandler("/status/targets", targetsTemplate)
	defHandler("/status/connections", connectionsTemplate)
	defHandler("/status/peers", peersTemplate)
	defHandler("/status/dns", dnsEntriesTemplate)
	defHandler("/status/ipam", ipamTemplate)

}
<commit_msg>Remove counting of ring tokens, since it isn't useful to end-user. Previously the count of tokens was claimed to be a count of addresses in use, which is incorrect. Also rename `appendAddresses` to `appendOwned` since it doesn't involve addresses.<commit_after>package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"text/template"

	"github.com/gorilla/mux"
	. "github.com/weaveworks/weave/common"
	"github.com/weaveworks/weave/ipam"
	"github.com/weaveworks/weave/mesh"
	"github.com/weaveworks/weave/nameserver"
	"github.com/weaveworks/weave/net/address"
	weave "github.com/weaveworks/weave/router"
)

var rootTemplate = template.New("root").Funcs(map[string]interface{}{
	"countDNSEntries": func(entries []nameserver.EntryStatus) int {
		count := 0
		for _, entry := range entries {
			if entry.Tombstone == 0 {
				count++
			}
		}
		return count
	},
	"upstreamServers": func(servers []string) string {
		if len(servers) == 0 {
			return "none"
		}
		return strings.Join(servers, ", ")
	},
	"printIPAMRanges": func(status ipam.Status) string {
		var buffer bytes.Buffer

		type stats struct {
			Ranges    []address.Range
			Reachable bool
		}

		peerStats := make(map[mesh.PeerName]*stats)

		for peer, ranges := range status.Ring.OwnedRangesByPeer() {
			s, found := peerStats[peer]
			if !found {
				s = &stats{Reachable: status.IsKnownPeer(peer)}
				peerStats[peer] = s
			}
			s.Ranges = append(s.Ranges, ranges...)
		}

		appendOwned := func(peer mesh.PeerName, nickName string, reachable bool, ranges []address.Range) {
			reachableStr := ""
			if !reachable {
				reachableStr = "- unreachable!"
			}
			ipsInRange := 0
			for _, chunk := range ranges {
				ipsInRange += int(chunk.Size())
			}
			percentageRanges := float32(ipsInRange) * 100.0 / float32(status.RangeNumIPs)

			displayName := peer.String() + "(" + nickName + ")"
			fmt.Fprintf(&buffer, "%20s: %8d IPs (%04.1f%% of total) %s\n",
				displayName, ipsInRange, percentageRanges, reachableStr)
		}

		// print the local addresses
		if ourStats := peerStats[status.OurName]; ourStats != nil {
			appendOwned(status.OurName, "local", true, ourStats.Ranges)
		}

		// and then the rest
		for peer, stats := range peerStats {
			if peer != status.OurName {
				nickname, found := status.Nicknames[peer]
				if !found {
					nickname = peer.String()
				}
				appendOwned(peer, nickname, stats.Reachable, stats.Ranges)
			}
		}

		return buffer.String()
	},
	"printConnectionCounts": func(conns []mesh.LocalConnectionStatus) string {
		counts := make(map[string]int)
		for _, conn := range conns {
			counts[conn.State]++
		}
		return printCounts(counts, []string{"established", "pending", "retrying", "failed", "connecting"})
	},
	"printPeerConnectionCounts": func(peers []mesh.PeerStatus) string {
		counts := make(map[string]int)
		for _, peer := range peers {
			for _, conn := range peer.Connections {
				if conn.Established {
					counts["established"]++
				} else {
					counts["pending"]++
				}
			}
		}
		return printCounts(counts, []string{"established", "pending"})
	},
	"printState": func(enabled bool) string {
		if enabled {
			return "enabled"
		}
		return "disabled"
	},
	"trimSuffix": strings.TrimSuffix,
})

// Print counts in a specified order
func printCounts(counts map[string]int, keys []string) string {
	var stringCounts []string
	for _, key := range keys {
		if count, ok := counts[key]; ok {
			stringCounts = append(stringCounts, fmt.Sprintf("%d %s", count, key))
		}
	}
	return strings.Join(stringCounts, ", ")
}

// Strip escaped newlines from template
func escape(template string) string {
	return strings.Replace(template, "\\\n", "", -1)
}

// Define a named template panicking on error
func defTemplate(name string, text string) *template.Template {
	return template.Must(rootTemplate.New(name).Parse(escape(text)))
}

var statusTemplate = defTemplate("status", `\
       Version: {{.Version}}

       Service: router
      Protocol: {{.Router.Protocol}} \
{{if eq .Router.ProtocolMinVersion .Router.ProtocolMaxVersion}}\
{{.Router.ProtocolMaxVersion}}\
{{else}}\
{{.Router.ProtocolMinVersion}}..{{.Router.ProtocolMaxVersion}}\
{{end}}
          Name: {{.Router.Name}}({{.Router.NickName}})
    Encryption: {{printState .Router.Encryption}}
 PeerDiscovery: {{printState .Router.PeerDiscovery}}
       Targets: {{len .Router.Targets}}
   Connections: {{len .Router.Connections}}{{with printConnectionCounts .Router.Connections}} ({{.}}){{end}}
         Peers: {{len .Router.Peers}}{{with printPeerConnectionCounts .Router.Peers}} (with {{.}} connections){{end}}
{{if .IPAM}}\

       Service: ipam
{{if .IPAM.Entries}}\
     Consensus: achieved
{{else if .IPAM.Paxos}}\
     Consensus: waiting (quorum: {{.IPAM.Paxos.Quorum}}, known: {{.IPAM.Paxos.KnownNodes}})
{{else}}\
     Consensus: deferred
{{end}}\
         Range: {{.IPAM.Range}}
 DefaultSubnet: {{.IPAM.DefaultSubnet}}
{{end}}\
{{if .DNS}}\

       Service: dns
        Domain: {{.DNS.Domain}}
      Upstream: {{upstreamServers .DNS.Upstream}}
           TTL: {{.DNS.TTL}}
       Entries: {{countDNSEntries .DNS.Entries}}
{{end}}\
`)

var targetsTemplate = defTemplate("targetsTemplate", `\
{{range .Router.Targets}}{{.}}
{{end}}\
`)

var connectionsTemplate = defTemplate("connectionsTemplate", `\
{{range .Router.Connections}}\
{{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} {{printf "%-11v" .State}} {{.Info}}
{{end}}\
`)

var peersTemplate = defTemplate("peers", `\
{{range .Router.Peers}}\
{{.Name}}({{.NickName}})
{{range .Connections}}\
   {{if .Outbound}}->{{else}}<-{{end}} {{printf "%-21v" .Address}} \
{{$nameNickName := printf "%v(%v)" .Name .NickName}}{{printf "%-32v" $nameNickName}} \
{{if .Established}}established{{else}}pending{{end}}
{{end}}\
{{end}}\
`)

var dnsEntriesTemplate = defTemplate("dnsEntries", `\
{{$domain := printf ".%v" .DNS.Domain}}\
{{range .DNS.Entries}}\
{{if eq .Tombstone 0}}\
{{$hostname := trimSuffix .Hostname $domain}}\
{{printf "%-12v" $hostname}} {{printf "%-15v" .Address}} {{printf "%12.12v" .ContainerID}} {{.Origin}}
{{end}}\
{{end}}\
`)

var ipamTemplate = defTemplate("ipamTemplate", `{{printIPAMRanges .IPAM}}`)

type WeaveStatus struct {
	Version string
	Router  *weave.NetworkRouterStatus `json:"Router,omitempty"`
	IPAM    *ipam.Status               `json:"IPAM,omitempty"`
	DNS     *nameserver.Status         `json:"DNS,omitempty"`
}

func HandleHTTP(muxRouter *mux.Router, version string, router *weave.NetworkRouter, allocator *ipam.Allocator, defaultSubnet address.CIDR, ns *nameserver.Nameserver, dnsserver *nameserver.DNSServer) {
	status := func() WeaveStatus {
		return WeaveStatus{
			version,
			weave.NewNetworkRouterStatus(router),
			ipam.NewStatus(allocator, defaultSubnet),
			nameserver.NewStatus(ns, dnsserver)}
	}
	muxRouter.Methods("GET").Path("/report").Headers("Accept", "application/json").HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			json, err := json.MarshalIndent(status(), "", "    ")
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				Log.Error("Error during report marshalling: ", err)
				return
			}
			w.Header().Set("Content-Type", "application/json")
			w.Write(json)
		})

	muxRouter.Methods("GET").Path("/report").Queries("format", "{format}").HandlerFunc(
		func(w http.ResponseWriter, r *http.Request) {
			formatTemplate, err := template.New("format").Parse(mux.Vars(r)["format"])
			if err != nil {
				http.Error(w, err.Error(), http.StatusBadRequest)
				return
			}
			if err := formatTemplate.Execute(w, status()); err != nil {
				http.Error(w, "error during template execution", http.StatusInternalServerError)
				Log.Error(err)
			}
		})

	defHandler := func(path string, template *template.Template) {
		muxRouter.Methods("GET").Path(path).HandlerFunc(
			func(w http.ResponseWriter, r *http.Request) {
				if err := template.Execute(w, status()); err != nil {
					http.Error(w, "error during template execution", http.StatusInternalServerError)
					Log.Error(err)
				}
			})
	}

	defHandler("/status", statusTemplate)
	defHandler("/status/targets", targetsTemplate)
	defHandler("/status/connections", connectionsTemplate)
	defHandler("/status/peers", peersTemplate)
	defHandler("/status/dns", dnsEntriesTemplate)
	defHandler("/status/ipam", ipamTemplate)

}
<|endoftext|>


<commit_before>// Copyright 2016 github.com/govend/govend. All rights reserved.
// Use of this source code is governed by an Apache 2.0
// license that can be found in the LICENSE file.

package deps

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/govend/govend/deps/repos"
	"github.com/govend/govend/imports"
	"github.com/govend/govend/manifest"
)

// Vend is the main function govend uses to vendor external packages.
func Vend(pkgs []string, update, verbose, results, lock bool, format string) error {

	// check the site is vendorable
	if err := Vendorable(); err != nil {
		return err
	}

	// attempt to load the manifest file
	m, err := manifest.Load(format)
	if err != nil {
		return err
	}

	// sync ensures that if a vendor is specified in the manifest, that the
	// repository structure is also currently present in the vendor directory,
	// this allows us to trust the manifest file
	mlen := 0
	if lock || update {

		// it is important to save the manifest length before syncing, so that
		// we can tell the difference and update the manifest file
		mlen = m.Len()

		m.Sync()
	}

	// if no packages were provided as arguments, assume the current directory is
	// a go project and scan it for external packages.
	if len(pkgs) == 0 {
		pkgs, err = imports.Scan(".")
		if err != nil {
			return err
		}
	}

	// download that dependency and any external deps it has
	pkglist := map[string]bool{}
	stack := newVendorStack(pkgs...)
	for !stack.empty() {

		// pop an import package path off the stack
		pkg := stack.pop()
		if _, ok := pkglist[pkg]; ok {
			continue
		}

		// use the network to gather some metadata on this repo
		repo, err := repos.Ping(pkg)
		if err != nil {
			if verbose {
				fmt.Printf("%s (bad ping): %s\n", pkg, err)
			}
			pkglist[pkg] = false
			continue
		}

		if verbose {
			fmt.Printf("%s\n", repo.ImportPath)
		}

		// check if the repo is missing from the manifest file
		vpath := filepath.Join("vendor", repo.ImportPath)
		if !m.Contains(repo.ImportPath) && !dirExists(vpath) || lock || update {
			rev, err := repos.Download(repo, "vendor", "latest")
			if err != nil {
				pkglist[pkg] = false
				continue
			}
			m.Append(repo.ImportPath, rev)
		} else {
			for _, vendor := range m.Vendors {
				if vendor.Path == repo.ImportPath {
					if _, err := repos.Download(repo, "vendor", vendor.Rev); err != nil {
						pkglist[pkg] = false
						continue
					}
				}
			}
		}

		vpkg := filepath.Join("vendor", pkg)
		deps, err := imports.Scan(vpkg, imports.SinglePackage)
		if err != nil {
			pkglist[pkg] = false
			continue
		}
		pkglist[pkg] = true

		// push
		stack.push(deps...)
	}

	if verbose && results {
		fmt.Printf("\npackages scanned: %d\n", len(pkglist))
		skipped := 0
		for _, ok := range pkglist {
			if !ok {
				skipped++
			}
		}
		fmt.Printf("packages skipped: %d\n", skipped)
		fmt.Printf("repos downloaded: %d\n", m.Len())
	}

	if lock || mlen > 0 {
		if err := m.Write(); err != nil {
			return err
		}
	}

	return nil
}

// writeBlanks writes a number of blank spaces.
func writeBlanks(num int) {
	for num > 0 {
		fmt.Printf(" ")
		num--
	}
}

func badImportPath(err error) bool {
	return strings.Contains(err.Error(), "unrecognized import path")
}

func dirExists(path string) bool {
	_, err := os.Stat(path)
	return !os.IsNotExist(err)
}
<commit_msg>fix verbose output and optimize network pings by flagging both repo root paths and repo packages import paths<commit_after>// Copyright 2016 github.com/govend/govend. All rights reserved.
// Use of this source code is governed by an Apache 2.0
// license that can be found in the LICENSE file.

package deps

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/govend/govend/deps/repos"
	"github.com/govend/govend/imports"
	"github.com/govend/govend/manifest"
)

// Vend is the main function govend uses to vendor external packages.
func Vend(pkgs []string, update, verbose, results, lock bool, format string) error {

	// check the site is vendorable
	if err := Vendorable(); err != nil {
		return err
	}

	// attempt to load the manifest file
	m, err := manifest.Load(format)
	if err != nil {
		return err
	}

	// sync ensures that if a vendor is specified in the manifest, that the
	// repository structure is also currently present in the vendor directory,
	// this allows us to trust the manifest file
	mlen := 0
	if lock || update {

		// it is important to save the manifest length before syncing, so that
		// we can tell the difference and update the manifest file
		mlen = m.Len()

		m.Sync()
	}

	// if no packages were provided as arguments, assume the current directory is
	// a go project and scan it for external packages.
	if len(pkgs) == 0 {
		pkgs, err = imports.Scan(".")
		if err != nil {
			return err
		}
	}

	// download that dependency and any external deps it has
	pkglist := map[string]bool{}
	stack := newVendorStack(pkgs...)
	for !stack.empty() {

		// pop an import package path off the stack
		pkg := stack.pop()
		if _, ok := pkglist[pkg]; ok {
			continue
		}

		// use the network to gather some metadata on this repo
		repo, err := repos.Ping(pkg)
		if err != nil {
			if verbose {
				fmt.Printf("%s (bad ping): %s\n", pkg, err)
			}
			pkglist[pkg] = false
			continue
		}

		if _, ok := pkglist[repo.ImportPath]; ok {
			pkglist[repo.ImportPath] = false
			continue
		}

		if verbose {
			fmt.Printf("%s\n", repo.ImportPath)
		}

		// check if the repo is missing from the manifest file
		vpath := filepath.Join("vendor", repo.ImportPath)
		if !m.Contains(repo.ImportPath) && !dirExists(vpath) || lock || update {
			rev, err := repos.Download(repo, "vendor", "latest")
			if err != nil {
				pkglist[pkg] = false
				continue
			}
			m.Append(repo.ImportPath, rev)
		} else {
			for _, vendor := range m.Vendors {
				if vendor.Path == repo.ImportPath {
					if _, err := repos.Download(repo, "vendor", vendor.Rev); err != nil {
						pkglist[pkg] = false
						continue
					}
				}
			}
		}

		vpkg := filepath.Join("vendor", pkg)
		deps, err := imports.Scan(vpkg, imports.SinglePackage)
		if err != nil {
			pkglist[pkg] = false
			continue
		}
		pkglist[pkg] = true
		pkglist[repo.ImportPath] = true

		// push
		stack.push(deps...)
	}

	if verbose && results {
		fmt.Printf("\npackages scanned: %d\n", len(pkglist))
		skipped := 0
		for _, ok := range pkglist {
			if !ok {
				skipped++
			}
		}
		fmt.Printf("packages skipped: %d\n", skipped)
		fmt.Printf("repos downloaded: %d\n", m.Len())
	}

	if lock || mlen > 0 {
		if err := m.Write(); err != nil {
			return err
		}
	}

	return nil
}

// writeBlanks writes a number of blank spaces.
func writeBlanks(num int) {
	for num > 0 {
		fmt.Printf(" ")
		num--
	}
}

func badImportPath(err error) bool {
	return strings.Contains(err.Error(), "unrecognized import path")
}

func dirExists(path string) bool {
	_, err := os.Stat(path)
	return !os.IsNotExist(err)
}
<|endoftext|>


<commit_before>package deter

import (
	"encoding/xml"
	"fmt"
	"github.com/cycps/addie"
	"github.com/deter-project/go-spi/spi"
	"log"
	"reflect"
)

func compComp(c *addie.Computer) spi.Computer {

	var _c spi.Computer
	_c.Name = c.Name
	_c.OSs = []spi.OS{spi.OS{Name: c.OS, Version: ""}}
	_c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     c.Start_script,
		},
	}

	for _, i := range c.Interfaces {
		_c.Interfaces = append(_c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity), spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return _c

}

var kryCount int

func simComp() spi.Computer {

	var c spi.Computer
	c.Name = fmt.Sprintf("kry%d", kryCount)
	kryCount++
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: ""}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "sim_init",
		},
	}

	c.Interfaces = append(c.Interfaces,
		spi.Interface{
			Name:      "eth0",
			Substrate: "krynet",
			Capacity:  spi.Capacity{1000.0, spi.Kind{"max"}},
			Latency:   spi.Latency{0, spi.Kind{"max"}},
		},
	)

	return c

}

func saxComp(s *addie.Sax) spi.Computer {

	var c spi.Computer
	c.Name = s.Name
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: ""}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "sax_init",
		},
	}

	c.Interfaces = append(c.Interfaces,
		spi.Interface{
			Name:      "eth0",
			Substrate: "krynet",
			Capacity:  spi.Capacity{1000.0, spi.Kind{"max"}},
			Latency:   spi.Latency{0, spi.Kind{"max"}},
		},
	)

	for _, i := range s.Interfaces {
		c.Interfaces = append(c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity), spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return c

}

func rtrComp(r *addie.Router) spi.Computer {

	var c spi.Computer
	c.Name = r.Name
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: "Router"}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "router_init",
		},
	}

	for _, i := range r.Interfaces {
		c.Interfaces = append(c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity), spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return c

}

func swSubstrate(sw *addie.Switch) spi.Substrate {

	var ss spi.Substrate
	ss.Name = sw.Name
	ss.Capacity = spi.Capacity{float64(sw.Capacity), spi.Kind{"max"}}
	ss.Latency = spi.Latency{float64(sw.Latency), spi.Kind{"max"}}

	return ss

}

func krySubstrate() spi.Substrate {

	var ks spi.Substrate
	ks.Name = "krynet"
	ks.Capacity = spi.Capacity{float64(1000.0), spi.Kind{"max"}}
	ks.Latency = spi.Latency{float64(0.0), spi.Kind{"max"}}

	return ks

}

func updateIfxSubstrate(ifxName, ssName string, c *spi.Computer) {

	for i, _ := range c.Interfaces {
		if c.Interfaces[i].Name == ifxName {
			c.Interfaces[i].Substrate = ssName
			break
		}
	}

}

func updateEndpoint(ssName string, ifr addie.NetIfRef, dsg *addie.Design,
	xp *spi.Experiment,
	cMap map[addie.Id]*spi.Computer) {

	e, ok := dsg.Elements[ifr.Id]

	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			ssName, ifr.Id)
		return
	}

	switch e.(type) {
	case addie.Computer:
		c := e.(addie.Computer)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[c.Id])

	case addie.Router:
		r := e.(addie.Router)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[r.Id])

	case addie.Sax:
		s := e.(addie.Sax)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[s.Id])

	default:
		log.Printf("p2p link '%s' references illegal element '%v'", ssName, ifr.Id)
	}

}

func linkSubstrate(link *addie.Link, dsg *addie.Design,
	xp *spi.Experiment,
	cMap map[addie.Id]*spi.Computer,
	sMap map[addie.Id]*spi.Substrate) *spi.Substrate {

	var ss spi.Substrate
	ss.Name = link.Name
	ss.Capacity = spi.Capacity{float64(link.Capacity), spi.Kind{"max"}}
	ss.Latency = spi.Latency{float64(link.Latency), spi.Kind{"max"}}

	a, ok := dsg.Elements[link.Endpoints[0].Id]
	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			link.Name, link.Endpoints[0].Id)
		return nil
	}
	b, ok := dsg.Elements[link.Endpoints[1].Id]
	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			link.Name, link.Endpoints[0].Id)
		return nil
	}

	ta := reflect.TypeOf(a).Name()
	tb := reflect.TypeOf(b).Name()

	taIsHost := ta == "Computer" || ta == "Router" || ta == "Sax"
	tbIsHost := tb == "Computer" || tb == "Router" || tb == "Sax"

	if taIsHost && tbIsHost {
		updateEndpoint(link.Name, link.Endpoints[0], dsg, xp, cMap)
		updateEndpoint(link.Name, link.Endpoints[1], dsg, xp, cMap)
		return &ss
	} else if taIsHost && !tbIsHost {
		sw := b.(addie.Switch)
		updateEndpoint(sw.Name, link.Endpoints[0], dsg, xp, cMap)
		return nil
	} else if !taIsHost && tbIsHost {
		sw := a.(addie.Switch)
		updateEndpoint(sw.Name, link.Endpoints[1], dsg, xp, cMap)
		return nil
	}

	return nil
}

func DesignTopDL(dsg *addie.Design) spi.Experiment {

	kryCount = 0

	var xp spi.Experiment

	cMap := make(map[addie.Id]*spi.Computer)
	sMap := make(map[addie.Id]*spi.Substrate)

	var links []*addie.Link

	for _, e := range dsg.Elements {

		switch e.(type) {
		case addie.Computer:
			c := e.(addie.Computer)
			_c := compComp(&c)
			cMap[c.Id] = &_c
			xp.Elements.Elements = append(xp.Elements.Elements, _c)

		case addie.Sax:
			s := e.(addie.Sax)
			c := saxComp(&s)
			cMap[s.Id] = &c
			xp.Elements.Elements = append(xp.Elements.Elements, c)

		case addie.Switch:
			sw := e.(addie.Switch)
			ss := swSubstrate(&sw)
			sMap[sw.Id] = &ss
			xp.Substrates = append(xp.Substrates, ss)

		case addie.Router:
			rtr := e.(addie.Router)
			c := rtrComp(&rtr)
			cMap[rtr.Id] = &c
			xp.Elements.Elements = append(xp.Elements.Elements, c)

		case addie.Link:
			lnk := e.(addie.Link)
			links = append(links, &lnk)
		}

	}

	xp.Elements.Elements = append(xp.Elements.Elements, simComp())
	xp.Substrates = append(xp.Substrates, krySubstrate())

	for _, l := range links {
		_l := linkSubstrate(l, dsg, &xp, cMap, sMap)
		if _l != nil {
			xp.Substrates = append(xp.Substrates, *_l)
		}
	}

	return xp
}

func CreateDeterXP(user string, dsg *addie.Design) error {

	xp := DesignTopDL(dsg)

	//create a session with the DeterLab SPI
	_, err := spi.Login("deterboss", "muffins")
	if err != nil {
		log.Println(err)
		return fmt.Errorf("unable to login as deterboss")
	}

	topdl, err := xml.MarshalIndent(xp, "  ", "  ")
	if err != nil {
		log.Println(err)
		return fmt.Errorf("failed to serialize topology to topdl xml")
	}

	createResponse, err := spi.CreateExperiment(
		user+":"+dsg.Name, "deterboss", string(topdl), false)

	if err != nil {
		log.Println(err)
		return fmt.Errorf("failed to create experiment")
	}
	log.Printf("createResponse: %v", createResponse)

	return nil
}
<commit_msg>mbps -> kbps patch/hack<commit_after>package deter

import (
	"encoding/xml"
	"fmt"
	"github.com/cycps/addie"
	"github.com/deter-project/go-spi/spi"
	"log"
	"reflect"
)

func compComp(c *addie.Computer) spi.Computer {

	var _c spi.Computer
	_c.Name = c.Name
	_c.OSs = []spi.OS{spi.OS{Name: c.OS, Version: ""}}
	_c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     c.Start_script,
		},
	}

	for _, i := range c.Interfaces {
		_c.Interfaces = append(_c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity) * 1000, spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return _c

}

var kryCount int

func simComp() spi.Computer {

	var c spi.Computer
	c.Name = fmt.Sprintf("kry%d", kryCount)
	kryCount++
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: ""}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "sim_init",
		},
	}

	c.Interfaces = append(c.Interfaces,
		spi.Interface{
			Name:      "eth0",
			Substrate: "krynet",
			Capacity:  spi.Capacity{1000.0 * 1000, spi.Kind{"max"}},
			Latency:   spi.Latency{0, spi.Kind{"max"}},
		},
	)

	return c

}

func saxComp(s *addie.Sax) spi.Computer {

	var c spi.Computer
	c.Name = s.Name
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: ""}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "sax_init",
		},
	}

	c.Interfaces = append(c.Interfaces,
		spi.Interface{
			Name:      "eth0",
			Substrate: "krynet",
			Capacity:  spi.Capacity{1000.0 * 1000, spi.Kind{"max"}},
			Latency:   spi.Latency{0, spi.Kind{"max"}},
		},
	)

	for _, i := range s.Interfaces {
		c.Interfaces = append(c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity) * 1000, spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return c

}

func rtrComp(r *addie.Router) spi.Computer {

	var c spi.Computer
	c.Name = r.Name
	c.OSs = []spi.OS{spi.OS{Name: "Ubuntu1404-64-STD", Version: "Router"}}
	c.Attributes = []spi.TopDLAttribute{
		spi.TopDLAttribute{
			Attribute: "type",
			Value:     "dl380g3",
		},
		spi.TopDLAttribute{
			Attribute: "containers:openvz_template",
			Value:     "ubuntu-14.04-x86_64",
		},
		spi.TopDLAttribute{
			Attribute: "osid",
			Value:     "Ubuntu1404-64-STD",
		},
		spi.TopDLAttribute{
			Attribute: "startup",
			Value:     "router_init",
		},
	}

	for _, i := range r.Interfaces {
		c.Interfaces = append(c.Interfaces,
			spi.Interface{
				Name:      i.Name,
				Substrate: "TODO", //this gets resolved when the links get added
				Capacity:  spi.Capacity{float64(i.Capacity) * 1000, spi.Kind{"max"}},
				Latency:   spi.Latency{float64(i.Latency), spi.Kind{"max"}},
			},
		)
	}

	return c

}

func swSubstrate(sw *addie.Switch) spi.Substrate {

	var ss spi.Substrate
	ss.Name = sw.Name
	ss.Capacity = spi.Capacity{float64(sw.Capacity) * 1000, spi.Kind{"max"}}
	ss.Latency = spi.Latency{float64(sw.Latency), spi.Kind{"max"}}

	return ss

}

func krySubstrate() spi.Substrate {

	var ks spi.Substrate
	ks.Name = "krynet"
	ks.Capacity = spi.Capacity{float64(1000.0) * 1000, spi.Kind{"max"}}
	ks.Latency = spi.Latency{float64(0.0), spi.Kind{"max"}}

	return ks

}

func updateIfxSubstrate(ifxName, ssName string, c *spi.Computer) {

	for i, _ := range c.Interfaces {
		if c.Interfaces[i].Name == ifxName {
			c.Interfaces[i].Substrate = ssName
			break
		}
	}

}

func updateEndpoint(ssName string, ifr addie.NetIfRef, dsg *addie.Design,
	xp *spi.Experiment,
	cMap map[addie.Id]*spi.Computer) {

	e, ok := dsg.Elements[ifr.Id]

	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			ssName, ifr.Id)
		return
	}

	switch e.(type) {
	case addie.Computer:
		c := e.(addie.Computer)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[c.Id])

	case addie.Router:
		r := e.(addie.Router)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[r.Id])

	case addie.Sax:
		s := e.(addie.Sax)
		updateIfxSubstrate(ifr.IfName, ssName, cMap[s.Id])

	default:
		log.Printf("p2p link '%s' references illegal element '%v'", ssName, ifr.Id)
	}

}

func linkSubstrate(link *addie.Link, dsg *addie.Design,
	xp *spi.Experiment,
	cMap map[addie.Id]*spi.Computer,
	sMap map[addie.Id]*spi.Substrate) *spi.Substrate {

	var ss spi.Substrate
	ss.Name = link.Name
	ss.Capacity = spi.Capacity{float64(link.Capacity) * 1000, spi.Kind{"max"}}
	ss.Latency = spi.Latency{float64(link.Latency), spi.Kind{"max"}}

	a, ok := dsg.Elements[link.Endpoints[0].Id]
	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			link.Name, link.Endpoints[0].Id)
		return nil
	}
	b, ok := dsg.Elements[link.Endpoints[1].Id]
	if !ok {
		log.Printf("link '%s' references element '%v' but no such element exists",
			link.Name, link.Endpoints[0].Id)
		return nil
	}

	ta := reflect.TypeOf(a).Name()
	tb := reflect.TypeOf(b).Name()

	taIsHost := ta == "Computer" || ta == "Router" || ta == "Sax"
	tbIsHost := tb == "Computer" || tb == "Router" || tb == "Sax"

	if taIsHost && tbIsHost {
		updateEndpoint(link.Name, link.Endpoints[0], dsg, xp, cMap)
		updateEndpoint(link.Name, link.Endpoints[1], dsg, xp, cMap)
		return &ss
	} else if taIsHost && !tbIsHost {
		sw := b.(addie.Switch)
		updateEndpoint(sw.Name, link.Endpoints[0], dsg, xp, cMap)
		return nil
	} else if !taIsHost && tbIsHost {
		sw := a.(addie.Switch)
		updateEndpoint(sw.Name, link.Endpoints[1], dsg, xp, cMap)
		return nil
	}

	return nil
}

func DesignTopDL(dsg *addie.Design) spi.Experiment {

	kryCount = 0

	var xp spi.Experiment

	cMap := make(map[addie.Id]*spi.Computer)
	sMap := make(map[addie.Id]*spi.Substrate)

	var links []*addie.Link

	for _, e := range dsg.Elements {

		switch e.(type) {
		case addie.Computer:
			c := e.(addie.Computer)
			_c := compComp(&c)
			cMap[c.Id] = &_c
			xp.Elements.Elements = append(xp.Elements.Elements, _c)

		case addie.Sax:
			s := e.(addie.Sax)
			c := saxComp(&s)
			cMap[s.Id] = &c
			xp.Elements.Elements = append(xp.Elements.Elements, c)

		case addie.Switch:
			sw := e.(addie.Switch)
			ss := swSubstrate(&sw)
			sMap[sw.Id] = &ss
			xp.Substrates = append(xp.Substrates, ss)

		case addie.Router:
			rtr := e.(addie.Router)
			c := rtrComp(&rtr)
			cMap[rtr.Id] = &c
			xp.Elements.Elements = append(xp.Elements.Elements, c)

		case addie.Link:
			lnk := e.(addie.Link)
			links = append(links, &lnk)
		}

	}

	xp.Elements.Elements = append(xp.Elements.Elements, simComp())
	xp.Substrates = append(xp.Substrates, krySubstrate())

	for _, l := range links {
		_l := linkSubstrate(l, dsg, &xp, cMap, sMap)
		if _l != nil {
			xp.Substrates = append(xp.Substrates, *_l)
		}
	}

	return xp
}

func CreateDeterXP(user string, dsg *addie.Design) error {

	xp := DesignTopDL(dsg)

	//create a session with the DeterLab SPI
	_, err := spi.Login("deterboss", "muffins")
	if err != nil {
		log.Println(err)
		return fmt.Errorf("unable to login as deterboss")
	}

	topdl, err := xml.MarshalIndent(xp, "  ", "  ")
	if err != nil {
		log.Println(err)
		return fmt.Errorf("failed to serialize topology to topdl xml")
	}

	createResponse, err := spi.CreateExperiment(
		user+":"+dsg.Name, "deterboss", string(topdl), false)

	if err != nil {
		log.Println(err)
		return fmt.Errorf("failed to create experiment")
	}
	log.Printf("createResponse: %v", createResponse)

	return nil
}
<|endoftext|>


<commit_before>package crypt

import (
	"bytes"
	"testing"
)

var clean = []byte{
	0x84, 0x50, 0x04, 0x01, 0x00, 0x00, 0x86, 0x02, 0xe1, 0x5b, 0x1d, 0xaf, 0x4b, 0xc2, 0x39, 0x06,
	0x6b, 0x25, 0x17, 0xd1, 0xcd, 0xdc, 0x39, 0x05, 0x00, 0x00, 0x5b, 0x30, 0x64, 0x61, 0x6c, 0x65,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}

var mutated = []byte{
	0x22, 0x27, 0x91, 0x7d, 0xa6, 0x77, 0x13, 0x7e, 0x47, 0x2c, 0x88, 0xd3, 0xed, 0xb5, 0xac, 0x7a,
	0xcd, 0x52, 0x82, 0xad, 0x6b, 0xab, 0xac, 0x79, 0xa6, 0x77, 0xce, 0x4c, 0xc2, 0x16, 0xf9, 0x19,
	0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c,
	0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c,
}

//func TestRead(t *testing.T) {
//    t.Run("Must return an error on short buffer", func(t *testing.T) {
//        b := [] byte{};
//        _, err := Read(b);
//        if err == nil {
//            t.Error("No error on short byte slice")
//        }
//    })
//    t.Run("Must return mutated header", func(t *testing.T) {
//        message, _ := Read(mutated);
//        t.Run("Must return appropiate query", func(t *testing.T) {
//            if message.header.Query != 0x5084 {
//                t.Error("Unexpected query!")
//            }
//        })
//        t.Run("Must return appropiate size", func(t *testing.T) {
//            if message.header.Size != 0x0104 {
//                t.Error( "Unexpected size!")
//            }
//        })
//        t.Run("Must return appropiate sequence", func(t *testing.T) {
//            if message.header.Sequence != 0x0286 {
//                t.Error( "Unexpected sequence!")
//            }
//        })
//    })
//}

func TestMutate(t *testing.T) {
	t.Run("Should return a mutated byte slice", func(t *testing.T) {
		mutation := ApplyMask(clean)
		if !bytes.Equal(mutation, mutated) {
			t.Error("Mutate(%x) = %x", clean, mutation)
		}
	})
}
<commit_msg>As of go 1.7 t.Errorf instead of t.Error<commit_after>package crypt

import (
	"bytes"
	"testing"
)

var clean = []byte{
	0x84, 0x50, 0x04, 0x01, 0x00, 0x00, 0x86, 0x02, 0xe1, 0x5b, 0x1d, 0xaf, 0x4b, 0xc2, 0x39, 0x06,
	0x6b, 0x25, 0x17, 0xd1, 0xcd, 0xdc, 0x39, 0x05, 0x00, 0x00, 0x5b, 0x30, 0x64, 0x61, 0x6c, 0x65,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}

var mutated = []byte{
	0x22, 0x27, 0x91, 0x7d, 0xa6, 0x77, 0x13, 0x7e, 0x47, 0x2c, 0x88, 0xd3, 0xed, 0xb5, 0xac, 0x7a,
	0xcd, 0x52, 0x82, 0xad, 0x6b, 0xab, 0xac, 0x79, 0xa6, 0x77, 0xce, 0x4c, 0xc2, 0x16, 0xf9, 0x19,
	0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c,
	0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c, 0xa6, 0x77, 0x95, 0x7c,
}

//func TestRead(t *testing.T) {
//    t.Run("Must return an error on short buffer", func(t *testing.T) {
//        b := [] byte{};
//        _, err := Read(b);
//        if err == nil {
//            t.Error("No error on short byte slice")
//        }
//    })
//    t.Run("Must return mutated header", func(t *testing.T) {
//        message, _ := Read(mutated);
//        t.Run("Must return appropiate query", func(t *testing.T) {
//            if message.header.Query != 0x5084 {
//                t.Error("Unexpected query!")
//            }
//        })
//        t.Run("Must return appropiate size", func(t *testing.T) {
//            if message.header.Size != 0x0104 {
//                t.Error( "Unexpected size!")
//            }
//        })
//        t.Run("Must return appropiate sequence", func(t *testing.T) {
//            if message.header.Sequence != 0x0286 {
//                t.Error( "Unexpected sequence!")
//            }
//        })
//    })
//}

func TestMutate(t *testing.T) {
	t.Run("Should return a mutated byte slice", func(t *testing.T) {
		mutation := ApplyMask(clean)
		if !bytes.Equal(mutation, mutated) {
			t.Errorf("Mutate(%x) = %x", clean, mutation)
		}
	})
}
<|endoftext|>


<commit_before>// +build linux

package fs

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
	"github.com/opencontainers/runc/libcontainer/configs"
)

const (
	cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes"
	cgroupMemoryLimit     = "memory.limit_in_bytes"
)

type MemoryGroup struct {
}

func (s *MemoryGroup) Name() string {
	return "memory"
}

func (s *MemoryGroup) Apply(path string, d *cgroupData) (err error) {
	if path == "" {
		return nil
	}
	if memoryAssigned(d.config) {
		if _, err := os.Stat(path); os.IsNotExist(err) {
			if err := os.MkdirAll(path, 0755); err != nil {
				return err
			}
			// Only enable kernel memory accouting when this cgroup
			// is created by libcontainer, otherwise we might get
			// error when people use `cgroupsPath` to join an existed
			// cgroup whose kernel memory is not initialized.
			if err := EnableKernelMemoryAccounting(path); err != nil {
				return err
			}
		}
	}
	defer func() {
		if err != nil {
			os.RemoveAll(path)
		}
	}()

	// We need to join memory cgroup after set memory limits, because
	// kmem.limit_in_bytes can only be set when the cgroup is empty.
	return join(path, d.pid)
}

func setMemory(path string, val int64) error {
	if val == 0 {
		return nil
	}

	return fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10))
}

func setSwap(path string, val int64) error {
	if val == 0 {
		return nil
	}

	return fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10))
}

func setMemoryAndSwap(path string, r *configs.Resources) error {
	// If the memory update is set to -1 and the swap is not explicitly
	// set, we should also set swap to -1, it means unlimited memory.
	if r.Memory == -1 && r.MemorySwap == 0 {
		// Only set swap if it's enabled in kernel
		if cgroups.PathExists(filepath.Join(path, cgroupMemorySwapLimit)) {
			r.MemorySwap = -1
		}
	}

	// When memory and swap memory are both set, we need to handle the cases
	// for updating container.
	if r.Memory != 0 && r.MemorySwap != 0 {
		curLimit, err := fscommon.GetCgroupParamUint(path, cgroupMemoryLimit)
		if err != nil {
			return err
		}

		// When update memory limit, we should adapt the write sequence
		// for memory and swap memory, so it won't fail because the new
		// value and the old value don't fit kernel's validation.
		if r.MemorySwap == -1 || curLimit < uint64(r.MemorySwap) {
			if err := setSwap(path, r.MemorySwap); err != nil {
				return err
			}
			if err := setMemory(path, r.Memory); err != nil {
				return err
			}
			return nil
		}
	}

	if err := setMemory(path, r.Memory); err != nil {
		return err
	}
	if err := setSwap(path, r.MemorySwap); err != nil {
		return err
	}

	return nil
}

func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
	if err := setMemoryAndSwap(path, cgroup.Resources); err != nil {
		return err
	}

	if cgroup.Resources.KernelMemory != 0 {
		if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil {
			return err
		}
	}

	if cgroup.Resources.MemoryReservation != 0 {
		if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
			return err
		}
	}

	if cgroup.Resources.KernelMemoryTCP != 0 {
		if err := fscommon.WriteFile(path, "memory.kmem.tcp.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemoryTCP, 10)); err != nil {
			return err
		}
	}
	if cgroup.Resources.OomKillDisable {
		if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil {
			return err
		}
	}
	if cgroup.Resources.MemorySwappiness == nil || int64(*cgroup.Resources.MemorySwappiness) == -1 {
		return nil
	} else if *cgroup.Resources.MemorySwappiness <= 100 {
		if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*cgroup.Resources.MemorySwappiness, 10)); err != nil {
			return err
		}
	} else {
		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", *cgroup.Resources.MemorySwappiness)
	}

	return nil
}

func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
	// Set stats from memory.stat.
	statsFile, err := fscommon.OpenFile(path, "memory.stat", os.O_RDONLY)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}
	defer statsFile.Close()

	sc := bufio.NewScanner(statsFile)
	for sc.Scan() {
		t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text())
		if err != nil {
			return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
		}
		stats.MemoryStats.Stats[t] = v
	}
	stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"]

	memoryUsage, err := getMemoryData(path, "")
	if err != nil {
		return err
	}
	stats.MemoryStats.Usage = memoryUsage
	swapUsage, err := getMemoryData(path, "memsw")
	if err != nil {
		return err
	}
	stats.MemoryStats.SwapUsage = swapUsage
	kernelUsage, err := getMemoryData(path, "kmem")
	if err != nil {
		return err
	}
	stats.MemoryStats.KernelUsage = kernelUsage
	kernelTCPUsage, err := getMemoryData(path, "kmem.tcp")
	if err != nil {
		return err
	}
	stats.MemoryStats.KernelTCPUsage = kernelTCPUsage

	value, err := fscommon.GetCgroupParamUint(path, "memory.use_hierarchy")
	if err != nil {
		return err
	}
	if value == 1 {
		stats.MemoryStats.UseHierarchy = true
	}

	pagesByNUMA, err := getPageUsageByNUMA(path)
	if err != nil {
		return err
	}
	stats.MemoryStats.PageUsageByNUMA = pagesByNUMA

	return nil
}

func memoryAssigned(cgroup *configs.Cgroup) bool {
	return cgroup.Resources.Memory != 0 ||
		cgroup.Resources.MemoryReservation != 0 ||
		cgroup.Resources.MemorySwap > 0 ||
		cgroup.Resources.KernelMemory > 0 ||
		cgroup.Resources.KernelMemoryTCP > 0 ||
		cgroup.Resources.OomKillDisable ||
		(cgroup.Resources.MemorySwappiness != nil && int64(*cgroup.Resources.MemorySwappiness) != -1)
}

func getMemoryData(path, name string) (cgroups.MemoryData, error) {
	memoryData := cgroups.MemoryData{}

	moduleName := "memory"
	if name != "" {
		moduleName = "memory." + name
	}
	var (
		usage    = moduleName + ".usage_in_bytes"
		maxUsage = moduleName + ".max_usage_in_bytes"
		failcnt  = moduleName + ".failcnt"
		limit    = moduleName + ".limit_in_bytes"
	)

	value, err := fscommon.GetCgroupParamUint(path, usage)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err)
	}
	memoryData.Usage = value
	value, err = fscommon.GetCgroupParamUint(path, maxUsage)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", maxUsage, err)
	}
	memoryData.MaxUsage = value
	value, err = fscommon.GetCgroupParamUint(path, failcnt)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", failcnt, err)
	}
	memoryData.Failcnt = value
	value, err = fscommon.GetCgroupParamUint(path, limit)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", limit, err)
	}
	memoryData.Limit = value

	return memoryData, nil
}

func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
	const (
		maxColumns = math.MaxUint8 + 1
		filename   = "memory.numa_stat"
	)
	stats := cgroups.PageUsageByNUMA{}

	file, err := fscommon.OpenFile(cgroupPath, filename, os.O_RDONLY)
	if os.IsNotExist(err) {
		return stats, nil
	} else if err != nil {
		return stats, err
	}

	// File format is documented in linux/Documentation/cgroup-v1/memory.txt
	// and it looks like this:
	//
	// total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		var field *cgroups.PageStats

		line := scanner.Text()
		columns := strings.SplitN(line, " ", maxColumns)
		for i, column := range columns {
			byNode := strings.SplitN(column, "=", 2)
			// Some custom kernels have non-standard fields, like
			//   numa_locality 0 0 0 0 0 0 0 0 0 0
			//   numa_exectime 0
			if len(byNode) < 2 {
				if i == 0 {
					// Ignore/skip those.
					break
				} else {
					// The first column was already validated,
					// so be strict to the rest.
					return stats, fmt.Errorf("malformed line %q in %s",
						line, filename)
				}
			}
			key, val := byNode[0], byNode[1]
			if i == 0 { // First column: key is name, val is total.
				field = getNUMAField(&stats, key)
				if field == nil { // unknown field (new kernel?)
					break
				}
				field.Total, err = strconv.ParseUint(val, 0, 64)
				if err != nil {
					return stats, err
				}
				field.Nodes = map[uint8]uint64{}
			} else { // Subsequent columns: key is N<id>, val is usage.
				if len(key) < 2 || key[0] != 'N' {
					// This is definitely an error.
					return stats, fmt.Errorf("malformed line %q in %s",
						line, filename)
				}

				n, err := strconv.ParseUint(key[1:], 10, 8)
				if err != nil {
					return cgroups.PageUsageByNUMA{}, err
				}

				usage, err := strconv.ParseUint(val, 10, 64)
				if err != nil {
					return cgroups.PageUsageByNUMA{}, err
				}

				field.Nodes[uint8(n)] = usage
			}

		}
	}
	err = scanner.Err()
	if err != nil {
		return cgroups.PageUsageByNUMA{}, err
	}

	return stats, nil
}

func getNUMAField(stats *cgroups.PageUsageByNUMA, name string) *cgroups.PageStats {
	switch name {
	case "total":
		return &stats.Total
	case "file":
		return &stats.File
	case "anon":
		return &stats.Anon
	case "unevictable":
		return &stats.Unevictable
	case "hierarchical_total":
		return &stats.Hierarchical.Total
	case "hierarchical_file":
		return &stats.Hierarchical.File
	case "hierarchical_anon":
		return &stats.Hierarchical.Anon
	case "hierarchical_unevictable":
		return &stats.Hierarchical.Unevictable
	}
	return nil
}
<commit_msg>libct/cg/fs/memory: handle EBUSY<commit_after>// +build linux

package fs

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/opencontainers/runc/libcontainer/cgroups"
	"github.com/opencontainers/runc/libcontainer/cgroups/fscommon"
	"github.com/opencontainers/runc/libcontainer/configs"
	"github.com/pkg/errors"
	"golang.org/x/sys/unix"
)

const (
	cgroupMemorySwapLimit = "memory.memsw.limit_in_bytes"
	cgroupMemoryLimit     = "memory.limit_in_bytes"
	cgroupMemoryUsage     = "memory.usage_in_bytes"
	cgroupMemoryMaxUsage  = "memory.max_usage_in_bytes"
)

type MemoryGroup struct {
}

func (s *MemoryGroup) Name() string {
	return "memory"
}

func (s *MemoryGroup) Apply(path string, d *cgroupData) (err error) {
	if path == "" {
		return nil
	}
	if memoryAssigned(d.config) {
		if _, err := os.Stat(path); os.IsNotExist(err) {
			if err := os.MkdirAll(path, 0755); err != nil {
				return err
			}
			// Only enable kernel memory accouting when this cgroup
			// is created by libcontainer, otherwise we might get
			// error when people use `cgroupsPath` to join an existed
			// cgroup whose kernel memory is not initialized.
			if err := EnableKernelMemoryAccounting(path); err != nil {
				return err
			}
		}
	}
	defer func() {
		if err != nil {
			os.RemoveAll(path)
		}
	}()

	// We need to join memory cgroup after set memory limits, because
	// kmem.limit_in_bytes can only be set when the cgroup is empty.
	return join(path, d.pid)
}

func setMemory(path string, val int64) error {
	if val == 0 {
		return nil
	}

	err := fscommon.WriteFile(path, cgroupMemoryLimit, strconv.FormatInt(val, 10))
	if !errors.Is(err, unix.EBUSY) {
		return err
	}

	// EBUSY means the kernel can't set new limit as it's too low
	// (lower than the current usage). Return more specific error.
	usage, err := fscommon.GetCgroupParamUint(path, cgroupMemoryUsage)
	if err != nil {
		return err
	}
	max, err := fscommon.GetCgroupParamUint(path, cgroupMemoryMaxUsage)
	if err != nil {
		return err
	}

	return errors.Errorf("unable to set memory limit to %d (current usage: %d, peak usage: %d)", val, usage, max)
}

func setSwap(path string, val int64) error {
	if val == 0 {
		return nil
	}

	return fscommon.WriteFile(path, cgroupMemorySwapLimit, strconv.FormatInt(val, 10))
}

func setMemoryAndSwap(path string, r *configs.Resources) error {
	// If the memory update is set to -1 and the swap is not explicitly
	// set, we should also set swap to -1, it means unlimited memory.
	if r.Memory == -1 && r.MemorySwap == 0 {
		// Only set swap if it's enabled in kernel
		if cgroups.PathExists(filepath.Join(path, cgroupMemorySwapLimit)) {
			r.MemorySwap = -1
		}
	}

	// When memory and swap memory are both set, we need to handle the cases
	// for updating container.
	if r.Memory != 0 && r.MemorySwap != 0 {
		curLimit, err := fscommon.GetCgroupParamUint(path, cgroupMemoryLimit)
		if err != nil {
			return err
		}

		// When update memory limit, we should adapt the write sequence
		// for memory and swap memory, so it won't fail because the new
		// value and the old value don't fit kernel's validation.
		if r.MemorySwap == -1 || curLimit < uint64(r.MemorySwap) {
			if err := setSwap(path, r.MemorySwap); err != nil {
				return err
			}
			if err := setMemory(path, r.Memory); err != nil {
				return err
			}
			return nil
		}
	}

	if err := setMemory(path, r.Memory); err != nil {
		return err
	}
	if err := setSwap(path, r.MemorySwap); err != nil {
		return err
	}

	return nil
}

func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error {
	if err := setMemoryAndSwap(path, cgroup.Resources); err != nil {
		return err
	}

	if cgroup.Resources.KernelMemory != 0 {
		if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil {
			return err
		}
	}

	if cgroup.Resources.MemoryReservation != 0 {
		if err := fscommon.WriteFile(path, "memory.soft_limit_in_bytes", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
			return err
		}
	}

	if cgroup.Resources.KernelMemoryTCP != 0 {
		if err := fscommon.WriteFile(path, "memory.kmem.tcp.limit_in_bytes", strconv.FormatInt(cgroup.Resources.KernelMemoryTCP, 10)); err != nil {
			return err
		}
	}
	if cgroup.Resources.OomKillDisable {
		if err := fscommon.WriteFile(path, "memory.oom_control", "1"); err != nil {
			return err
		}
	}
	if cgroup.Resources.MemorySwappiness == nil || int64(*cgroup.Resources.MemorySwappiness) == -1 {
		return nil
	} else if *cgroup.Resources.MemorySwappiness <= 100 {
		if err := fscommon.WriteFile(path, "memory.swappiness", strconv.FormatUint(*cgroup.Resources.MemorySwappiness, 10)); err != nil {
			return err
		}
	} else {
		return fmt.Errorf("invalid value:%d. valid memory swappiness range is 0-100", *cgroup.Resources.MemorySwappiness)
	}

	return nil
}

func (s *MemoryGroup) GetStats(path string, stats *cgroups.Stats) error {
	// Set stats from memory.stat.
	statsFile, err := fscommon.OpenFile(path, "memory.stat", os.O_RDONLY)
	if err != nil {
		if os.IsNotExist(err) {
			return nil
		}
		return err
	}
	defer statsFile.Close()

	sc := bufio.NewScanner(statsFile)
	for sc.Scan() {
		t, v, err := fscommon.GetCgroupParamKeyValue(sc.Text())
		if err != nil {
			return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
		}
		stats.MemoryStats.Stats[t] = v
	}
	stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"]

	memoryUsage, err := getMemoryData(path, "")
	if err != nil {
		return err
	}
	stats.MemoryStats.Usage = memoryUsage
	swapUsage, err := getMemoryData(path, "memsw")
	if err != nil {
		return err
	}
	stats.MemoryStats.SwapUsage = swapUsage
	kernelUsage, err := getMemoryData(path, "kmem")
	if err != nil {
		return err
	}
	stats.MemoryStats.KernelUsage = kernelUsage
	kernelTCPUsage, err := getMemoryData(path, "kmem.tcp")
	if err != nil {
		return err
	}
	stats.MemoryStats.KernelTCPUsage = kernelTCPUsage

	value, err := fscommon.GetCgroupParamUint(path, "memory.use_hierarchy")
	if err != nil {
		return err
	}
	if value == 1 {
		stats.MemoryStats.UseHierarchy = true
	}

	pagesByNUMA, err := getPageUsageByNUMA(path)
	if err != nil {
		return err
	}
	stats.MemoryStats.PageUsageByNUMA = pagesByNUMA

	return nil
}

func memoryAssigned(cgroup *configs.Cgroup) bool {
	return cgroup.Resources.Memory != 0 ||
		cgroup.Resources.MemoryReservation != 0 ||
		cgroup.Resources.MemorySwap > 0 ||
		cgroup.Resources.KernelMemory > 0 ||
		cgroup.Resources.KernelMemoryTCP > 0 ||
		cgroup.Resources.OomKillDisable ||
		(cgroup.Resources.MemorySwappiness != nil && int64(*cgroup.Resources.MemorySwappiness) != -1)
}

func getMemoryData(path, name string) (cgroups.MemoryData, error) {
	memoryData := cgroups.MemoryData{}

	moduleName := "memory"
	if name != "" {
		moduleName = "memory." + name
	}
	var (
		usage    = moduleName + ".usage_in_bytes"
		maxUsage = moduleName + ".max_usage_in_bytes"
		failcnt  = moduleName + ".failcnt"
		limit    = moduleName + ".limit_in_bytes"
	)

	value, err := fscommon.GetCgroupParamUint(path, usage)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err)
	}
	memoryData.Usage = value
	value, err = fscommon.GetCgroupParamUint(path, maxUsage)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", maxUsage, err)
	}
	memoryData.MaxUsage = value
	value, err = fscommon.GetCgroupParamUint(path, failcnt)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", failcnt, err)
	}
	memoryData.Failcnt = value
	value, err = fscommon.GetCgroupParamUint(path, limit)
	if err != nil {
		if moduleName != "memory" && os.IsNotExist(err) {
			return cgroups.MemoryData{}, nil
		}
		return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", limit, err)
	}
	memoryData.Limit = value

	return memoryData, nil
}

func getPageUsageByNUMA(cgroupPath string) (cgroups.PageUsageByNUMA, error) {
	const (
		maxColumns = math.MaxUint8 + 1
		filename   = "memory.numa_stat"
	)
	stats := cgroups.PageUsageByNUMA{}

	file, err := fscommon.OpenFile(cgroupPath, filename, os.O_RDONLY)
	if os.IsNotExist(err) {
		return stats, nil
	} else if err != nil {
		return stats, err
	}

	// File format is documented in linux/Documentation/cgroup-v1/memory.txt
	// and it looks like this:
	//
	// total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
	// hierarchical_<counter>=<counter pages> N0=<node 0 pages> N1=<node 1 pages> ...

	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		var field *cgroups.PageStats

		line := scanner.Text()
		columns := strings.SplitN(line, " ", maxColumns)
		for i, column := range columns {
			byNode := strings.SplitN(column, "=", 2)
			// Some custom kernels have non-standard fields, like
			//   numa_locality 0 0 0 0 0 0 0 0 0 0
			//   numa_exectime 0
			if len(byNode) < 2 {
				if i == 0 {
					// Ignore/skip those.
					break
				} else {
					// The first column was already validated,
					// so be strict to the rest.
					return stats, fmt.Errorf("malformed line %q in %s",
						line, filename)
				}
			}
			key, val := byNode[0], byNode[1]
			if i == 0 { // First column: key is name, val is total.
				field = getNUMAField(&stats, key)
				if field == nil { // unknown field (new kernel?)
					break
				}
				field.Total, err = strconv.ParseUint(val, 0, 64)
				if err != nil {
					return stats, err
				}
				field.Nodes = map[uint8]uint64{}
			} else { // Subsequent columns: key is N<id>, val is usage.
				if len(key) < 2 || key[0] != 'N' {
					// This is definitely an error.
					return stats, fmt.Errorf("malformed line %q in %s",
						line, filename)
				}

				n, err := strconv.ParseUint(key[1:], 10, 8)
				if err != nil {
					return cgroups.PageUsageByNUMA{}, err
				}

				usage, err := strconv.ParseUint(val, 10, 64)
				if err != nil {
					return cgroups.PageUsageByNUMA{}, err
				}

				field.Nodes[uint8(n)] = usage
			}

		}
	}
	err = scanner.Err()
	if err != nil {
		return cgroups.PageUsageByNUMA{}, err
	}

	return stats, nil
}

func getNUMAField(stats *cgroups.PageUsageByNUMA, name string) *cgroups.PageStats {
	switch name {
	case "total":
		return &stats.Total
	case "file":
		return &stats.File
	case "anon":
		return &stats.Anon
	case "unevictable":
		return &stats.Unevictable
	case "hierarchical_total":
		return &stats.Hierarchical.Total
	case "hierarchical_file":
		return &stats.Hierarchical.File
	case "hierarchical_anon":
		return &stats.Hierarchical.Anon
	case "hierarchical_unevictable":
		return &stats.Hierarchical.Unevictable
	}
	return nil
}
<|endoftext|>


<commit_before>package daemon

import (
	"syscall"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/oci"
	"github.com/docker/docker/pkg/sysinfo"
	"github.com/opencontainers/runtime-spec/specs-go"
)

func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
	s := oci.DefaultSpec()

	linkedEnv, err := daemon.setupLinkedContainers(c)
	if err != nil {
		return nil, err
	}

	// Note, unlike Unix, we do NOT call into SetupWorkingDirectory as
	// this is done in VMCompute. Further, we couldn't do it for Hyper-V
	// containers anyway.

	// In base spec
	s.Hostname = c.FullHostname()

	// In s.Mounts
	mounts, err := daemon.setupMounts(c)
	if err != nil {
		return nil, err
	}
	for _, mount := range mounts {
		m := specs.Mount{
			Source:      mount.Source,
			Destination: mount.Destination,
		}
		if !mount.Writable {
			m.Options = append(m.Options, "ro")
		}
		s.Mounts = append(s.Mounts, m)
	}

	// In s.Process
	s.Process.Args = append([]string{c.Path}, c.Args...)
	if !c.Config.ArgsEscaped {
		s.Process.Args = escapeArgs(s.Process.Args)
	}
	s.Process.Cwd = c.Config.WorkingDir
	if len(s.Process.Cwd) == 0 {
		// We default to C:\ to workaround the oddity of the case that the
		// default directory for cmd running as LocalSystem (or
		// ContainerAdministrator) is c:\windows\system32. Hence docker run
		// <image> cmd will by default end in c:\windows\system32, rather
		// than 'root' (/) on Linux. The oddity is that if you have a dockerfile
		// which has no WORKDIR and has a COPY file ., . will be interpreted
		// as c:\. Hence, setting it to default of c:\ makes for consistency.
		s.Process.Cwd = `C:\`
	}
	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
	s.Process.ConsoleSize.Height = c.HostConfig.ConsoleSize[0]
	s.Process.ConsoleSize.Width = c.HostConfig.ConsoleSize[1]
	s.Process.Terminal = c.Config.Tty
	s.Process.User.Username = c.Config.User

	// In spec.Root. This is not set for Hyper-V containers
	var isHyperV bool
	if c.HostConfig.Isolation.IsDefault() {
		// Container using default isolation, so take the default from the daemon configuration
		isHyperV = daemon.defaultIsolation.IsHyperV()
	} else {
		// Container may be requesting an explicit isolation mode.
		isHyperV = c.HostConfig.Isolation.IsHyperV()
	}
	if !isHyperV {
		s.Root.Path = c.BaseFS
	}
	s.Root.Readonly = false // Windows does not support a read-only root filesystem

	// In s.Windows.Resources
	// @darrenstahlmsft implement these resources
	cpuShares := uint16(c.HostConfig.CPUShares)
	cpuPercent := uint8(c.HostConfig.CPUPercent)
	cpuCount := uint64(c.HostConfig.CPUCount)
	if c.HostConfig.NanoCPUs > 0 {
		if isHyperV {
			cpuCount = uint64(c.HostConfig.NanoCPUs / 1e9)
			leftoverNanoCPUs := c.HostConfig.NanoCPUs % 1e9
			if leftoverNanoCPUs != 0 {
				cpuCount++
				cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(cpuCount) / 1e9)
			}
		} else {
			cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(sysinfo.NumCPU()) / 1e9)
		}
	}
	memoryLimit := uint64(c.HostConfig.Memory)
	s.Windows.Resources = &specs.WindowsResources{
		CPU: &specs.WindowsCPUResources{
			Percent: &cpuPercent,
			Shares:  &cpuShares,
			Count:   &cpuCount,
		},
		Memory: &specs.WindowsMemoryResources{
			Limit: &memoryLimit,
			//TODO Reservation: ...,
		},
		Network: &specs.WindowsNetworkResources{
		//TODO Bandwidth: ...,
		},
		Storage: &specs.WindowsStorageResources{
			Bps:  &c.HostConfig.IOMaximumBandwidth,
			Iops: &c.HostConfig.IOMaximumIOps,
		},
	}
	return (*specs.Spec)(&s), nil
}

func escapeArgs(args []string) []string {
	escapedArgs := make([]string, len(args))
	for i, a := range args {
		escapedArgs[i] = syscall.EscapeArg(a)
	}
	return escapedArgs
}

// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
// It will do nothing on non-Linux platform
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
	return
}
<commit_msg>Prevent a non-zero NanoCPUs from setting a zero CPU.Count<commit_after>package daemon

import (
	"syscall"

	containertypes "github.com/docker/docker/api/types/container"
	"github.com/docker/docker/container"
	"github.com/docker/docker/oci"
	"github.com/docker/docker/pkg/sysinfo"
	"github.com/opencontainers/runtime-spec/specs-go"
)

func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
	s := oci.DefaultSpec()

	linkedEnv, err := daemon.setupLinkedContainers(c)
	if err != nil {
		return nil, err
	}

	// Note, unlike Unix, we do NOT call into SetupWorkingDirectory as
	// this is done in VMCompute. Further, we couldn't do it for Hyper-V
	// containers anyway.

	// In base spec
	s.Hostname = c.FullHostname()

	// In s.Mounts
	mounts, err := daemon.setupMounts(c)
	if err != nil {
		return nil, err
	}
	for _, mount := range mounts {
		m := specs.Mount{
			Source:      mount.Source,
			Destination: mount.Destination,
		}
		if !mount.Writable {
			m.Options = append(m.Options, "ro")
		}
		s.Mounts = append(s.Mounts, m)
	}

	// In s.Process
	s.Process.Args = append([]string{c.Path}, c.Args...)
	if !c.Config.ArgsEscaped {
		s.Process.Args = escapeArgs(s.Process.Args)
	}
	s.Process.Cwd = c.Config.WorkingDir
	if len(s.Process.Cwd) == 0 {
		// We default to C:\ to workaround the oddity of the case that the
		// default directory for cmd running as LocalSystem (or
		// ContainerAdministrator) is c:\windows\system32. Hence docker run
		// <image> cmd will by default end in c:\windows\system32, rather
		// than 'root' (/) on Linux. The oddity is that if you have a dockerfile
		// which has no WORKDIR and has a COPY file ., . will be interpreted
		// as c:\. Hence, setting it to default of c:\ makes for consistency.
		s.Process.Cwd = `C:\`
	}
	s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv)
	s.Process.ConsoleSize.Height = c.HostConfig.ConsoleSize[0]
	s.Process.ConsoleSize.Width = c.HostConfig.ConsoleSize[1]
	s.Process.Terminal = c.Config.Tty
	s.Process.User.Username = c.Config.User

	// In spec.Root. This is not set for Hyper-V containers
	var isHyperV bool
	if c.HostConfig.Isolation.IsDefault() {
		// Container using default isolation, so take the default from the daemon configuration
		isHyperV = daemon.defaultIsolation.IsHyperV()
	} else {
		// Container may be requesting an explicit isolation mode.
		isHyperV = c.HostConfig.Isolation.IsHyperV()
	}
	if !isHyperV {
		s.Root.Path = c.BaseFS
	}
	s.Root.Readonly = false // Windows does not support a read-only root filesystem

	// In s.Windows.Resources
	// @darrenstahlmsft implement these resources
	cpuShares := uint16(c.HostConfig.CPUShares)
	cpuPercent := uint8(c.HostConfig.CPUPercent)
	cpuCount := uint64(c.HostConfig.CPUCount)
	if c.HostConfig.NanoCPUs > 0 {
		if isHyperV {
			cpuCount = uint64(c.HostConfig.NanoCPUs / 1e9)
			leftoverNanoCPUs := c.HostConfig.NanoCPUs % 1e9
			if leftoverNanoCPUs != 0 {
				cpuCount++
				cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(cpuCount) / 1e9)
			}
		} else {
			cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(sysinfo.NumCPU()) / 1e9)

			if cpuPercent < 1 {
				// The requested NanoCPUs is so small that we rounded to 0, use 1 instead
				cpuPercent = 1
			}
		}
	}
	memoryLimit := uint64(c.HostConfig.Memory)
	s.Windows.Resources = &specs.WindowsResources{
		CPU: &specs.WindowsCPUResources{
			Percent: &cpuPercent,
			Shares:  &cpuShares,
			Count:   &cpuCount,
		},
		Memory: &specs.WindowsMemoryResources{
			Limit: &memoryLimit,
			//TODO Reservation: ...,
		},
		Network: &specs.WindowsNetworkResources{
		//TODO Bandwidth: ...,
		},
		Storage: &specs.WindowsStorageResources{
			Bps:  &c.HostConfig.IOMaximumBandwidth,
			Iops: &c.HostConfig.IOMaximumIOps,
		},
	}
	return (*specs.Spec)(&s), nil
}

func escapeArgs(args []string) []string {
	escapedArgs := make([]string, len(args))
	for i, a := range args {
		escapedArgs[i] = syscall.EscapeArg(a)
	}
	return escapedArgs
}

// mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig
// It will do nothing on non-Linux platform
func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) {
	return
}
<|endoftext|>


<commit_before>package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
	"log"
)

type App struct {
	*revel.Controller
}

func (a App) Search(query string) revel.Result {
	fmt.Println("Searching for... ", query)
	api.Domain = "localhost"
	searchJson := fmt.Sprintf(`{"query": { "multi_match" : {"query" : "%s", "fields" : ["romaji", "furigana", "japanese", "glosses"]}}}`, query)
	out, err := core.SearchRequest(true, "edict", "entry", searchJson, "", 0)
	if err != nil {
		log.Println(err)
	}

	type Word struct {
		Romaji   string
		Common   bool
		Dialects []string
		Fields   []string
		Glosses  []string
		Furigana string
		Japanese string
		Tags     []string
		Pos      []string
	}

	hits := [][]byte{}
	for _, hit := range out.Hits.Hits {
		hits = append(hits, hit.Source)
	}

	wordList := []Word{}
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			fmt.Println(err)
		}
		wordList = append(wordList, w)
	}

	return a.Render(wordList)
}

func (c App) Index() revel.Result {
	return c.Render()
}
<commit_msg>use log instead of fmt<commit_after>package controllers

import (
	"encoding/json"
	"fmt"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
	"log"
)

type App struct {
	*revel.Controller
}

func (a App) Search(query string) revel.Result {
	fmt.Println("Searching for... ", query)
	api.Domain = "localhost"
	searchJson := fmt.Sprintf(`{"query": { "multi_match" : {"query" : "%s", "fields" : ["romaji", "furigana", "japanese", "glosses"]}}}`, query)
	out, err := core.SearchRequest(true, "edict", "entry", searchJson, "", 0)
	if err != nil {
		log.Println(err)
	}

	type Word struct {
		Romaji   string
		Common   bool
		Dialects []string
		Fields   []string
		Glosses  []string
		Furigana string
		Japanese string
		Tags     []string
		Pos      []string
	}

	hits := [][]byte{}
	for _, hit := range out.Hits.Hits {
		hits = append(hits, hit.Source)
	}

	wordList := []Word{}
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			log.Println(err)
		}
		wordList = append(wordList, w)
	}

	return a.Render(wordList)
}

func (c App) Index() revel.Result {
	return c.Render()
}
<|endoftext|>


<commit_before>package controllers

import (
	"fmt"
	//"github.com/gojp/nihongo/app/models"
	//"github.com/mattbaird/elastigo/api"
	//"github.com/mattbaird/elastigo/search"
	//"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
)

type App struct {
	*revel.Controller
}

func (a App) Search(query string) revel.Result {
	//api.Domain = "localhost"
	//out, err := search.Search("edict").Type("entry").Size("100").Search(query).Result()
	//if err != nil {
	//	fmt.Println(err)
	//}
	//fmt.Println(out)

	fmt.Println("Searching for... ", query)

	// Index - not the best place for this, but okay for now...
	//index := mgo.Index{
	//	Key:        []string{"romaji", "furigana", "japanese", "glosses"},
	//	Unique:     false,
	//	DropDups:   false,
	//	Background: true,
	//	Sparse:     true,
	//}

	//err := collection.EnsureIndex(index)

	//if err != nil {
	//	panic("Database connection failed")
	//}

	//wordList := []models.Word{}
	//query := bson.M{"$or": []bson.M{
	//	bson.M{"romaji": bson.RegEx{".*" + search + ".*", "i"}},
	//	bson.M{"furigana": search},
	//	bson.M{"japanese": search},
	//}}
	//q := collection.Find(query).Sort("-common", "furigana")
	//iter := q.Limit(100).Iter()
	//iter.All(&wordList)

	return a.Render()
}

func (c App) Index() revel.Result {
	return c.Render()
}
<commit_msg>make search endpoint use elasticsearch<commit_after>package controllers

import (
	"encoding/json"
	"fmt"
	//"github.com/gojp/nihongo/app/models"
	"github.com/mattbaird/elastigo/api"
	"github.com/mattbaird/elastigo/core"
	"github.com/robfig/revel"
	"log"
)

type App struct {
	*revel.Controller
}

func (a App) Search(query string) revel.Result {
	fmt.Println("Searching for... ", query)
	api.Domain = "localhost"
	searchJson := fmt.Sprintf(`{"query": { "multi_match" : {"query" : "%s", "fields" : ["romaji", "furigana", "japanese", "glosses"]}}}`, query)
	out, err := core.SearchRequest(true, "edict", "entry", searchJson, "", 0)
	if err != nil {
		log.Println(err)
	}

	type Word struct {
		Romaji   string
		Common   bool
		Dialects []string
		Fields   []string
		Glosses  []string
		Furigana string
		Japanese string
		Tags     []string
		Pos      []string
	}

	hits := [][]byte{}
	for _, hit := range out.Hits.Hits {
		hits = append(hits, hit.Source)
	}

	wordList := []Word{}
	for _, hit := range hits {
		w := Word{}
		err := json.Unmarshal(hit, &w)
		if err != nil {
			fmt.Println(err)
		}
		wordList = append(wordList, w)
	}

	return a.Render(wordList)
}

func (c App) Index() revel.Result {
	return c.Render()
}
<|endoftext|>