<commit_before>package infrastructure_test

import (
	//	"fmt"
	"net/http"
	"net/http/httptest"
	//	"net/url"
	//	"strings"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	"bosh/errors"
	. "bosh/infrastructure"
	fakeinf "bosh/infrastructure/fakes"
	"fmt"
)

var _ = Describe("concreteMetadataService", func() {
	var (
		dnsResolver     *fakeinf.FakeDNSResolver
		metadataService MetadataService
	)

	BeforeEach(func() {
		dnsResolver = &fakeinf.FakeDNSResolver{}
		metadataService = NewConcreteMetadataService("fake-metadata-host", dnsResolver)
	})

	Describe("GetPublicKey", func() {
		var (
			ts *httptest.Server
		)

		BeforeEach(func() {
			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				Expect(r.Method).To(Equal("GET"))
				Expect(r.URL.Path).To(Equal("/latest/meta-data/public-keys/0/openssh-key"))
				w.Write([]byte("fake-public-key"))
			})

			ts = httptest.NewServer(handler)

			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		It("returns fetched public key", func() {
			publicKey, err := metadataService.GetPublicKey()
			Expect(err).NotTo(HaveOccurred())
			Expect(publicKey).To(Equal("fake-public-key"))
		})
	})

	Describe("GetInstanceID", func() {
		var (
			ts *httptest.Server
		)

		BeforeEach(func() {
			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				Expect(r.Method).To(Equal("GET"))
				Expect(r.URL.Path).To(Equal("/latest/meta-data/instance-id"))
				w.Write([]byte("fake-instance-id"))
			})

			ts = httptest.NewServer(handler)

			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		It("returns fetched instance id", func() {
			publicKey, err := metadataService.GetInstanceID()
			Expect(err).NotTo(HaveOccurred())
			Expect(publicKey).To(Equal("fake-instance-id"))
		})
	})

	Describe("GetRegistryEndpoint", func() {
		var (
			ts          *httptest.Server
			registryURL *string
			dnsServer   *string
		)

		handlerFunc := func(w http.ResponseWriter, r *http.Request) {
			Expect(r.Method).To(Equal("GET"))
			Expect(r.URL.Path).To(Equal("/latest/user-data"))

			var jsonStr string

			if dnsServer == nil {
				jsonStr = fmt.Sprintf(`{"registry":{"endpoint":"%s"}}`, *registryURL)
			} else {
				jsonStr = fmt.Sprintf(`{
					"registry":{"endpoint":"%s"},
					"dns":{"nameserver":["%s"]}
				}`, *registryURL, *dnsServer)
			}

			w.Write([]byte(jsonStr))
		}

		BeforeEach(func() {
			url := "http://fake-registry.com"
			registryURL = &url
			dnsServer = nil

			handler := http.HandlerFunc(handlerFunc)
			ts = httptest.NewServer(handler)
			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		Context("when metadata contains a dns server", func() {
			BeforeEach(func() {
				server := "fake-dns-server-ip"
				dnsServer = &server
			})

			Context("when registry endpoint is successfully resolved", func() {
				BeforeEach(func() {
					dnsResolver.RegisterRecord(fakeinf.FakeDNSRecord{
						DNSServers: []string{"fake-dns-server-ip"},
						Host:       "fake-registry.com",
						IP:         "fake-registry-ip",
					})
				})

				Context("when registry endpoint has a port", func() {
					BeforeEach(func() {
						url := "http://fake-registry.com:8877"
						registryURL = &url
					})

					It("returns the successfully resolved registry endpoint with port", func() {
						endpoint, err := metadataService.GetRegistryEndpoint()
						Expect(err).ToNot(HaveOccurred())
						Expect(endpoint).To(Equal("http://fake-registry-ip:8877"))
					})
				})

				Context("when registry endpoint does not have a port", func() {
					BeforeEach(func() {
						url := "http://fake-registry.com"
						registryURL = &url
					})

					It("returns the successfully resolved registry endpoint", func() {
						endpoint, err := metadataService.GetRegistryEndpoint()
						Expect(err).ToNot(HaveOccurred())
						Expect(endpoint).To(Equal("http://fake-registry-ip"))
					})
				})
			})

			Context("when registry endpoint is not successfully resolved", func() {
				BeforeEach(func() {
					dnsResolver.LookupHostErr = errors.New("fake-lookup-host-err")
				})

				It("returns error because it failed to resolve registry endpoint", func() {
					endpoint, err := metadataService.GetRegistryEndpoint()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("fake-lookup-host-err"))
					Expect(endpoint).To(BeEmpty())
				})
			})
		})

		Context("when metadata does not contain dns servers", func() {
			It("returns fetched registry endpoint", func() {
				endpoint, err := metadataService.GetRegistryEndpoint()
				Expect(err).NotTo(HaveOccurred())
				Expect(endpoint).To(Equal("http://fake-registry.com"))
			})
		})
	})
})
<commit_msg>clened up import<commit_after>package infrastructure_test

import (
	"errors"
	"fmt"
	"net/http"
	"net/http/httptest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"

	. "bosh/infrastructure"
	fakeinf "bosh/infrastructure/fakes"
)

var _ = Describe("concreteMetadataService", func() {
	var (
		dnsResolver     *fakeinf.FakeDNSResolver
		metadataService MetadataService
	)

	BeforeEach(func() {
		dnsResolver = &fakeinf.FakeDNSResolver{}
		metadataService = NewConcreteMetadataService("fake-metadata-host", dnsResolver)
	})

	Describe("GetPublicKey", func() {
		var (
			ts *httptest.Server
		)

		BeforeEach(func() {
			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				Expect(r.Method).To(Equal("GET"))
				Expect(r.URL.Path).To(Equal("/latest/meta-data/public-keys/0/openssh-key"))
				w.Write([]byte("fake-public-key"))
			})

			ts = httptest.NewServer(handler)

			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		It("returns fetched public key", func() {
			publicKey, err := metadataService.GetPublicKey()
			Expect(err).NotTo(HaveOccurred())
			Expect(publicKey).To(Equal("fake-public-key"))
		})
	})

	Describe("GetInstanceID", func() {
		var (
			ts *httptest.Server
		)

		BeforeEach(func() {
			handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				Expect(r.Method).To(Equal("GET"))
				Expect(r.URL.Path).To(Equal("/latest/meta-data/instance-id"))
				w.Write([]byte("fake-instance-id"))
			})

			ts = httptest.NewServer(handler)

			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		It("returns fetched instance id", func() {
			publicKey, err := metadataService.GetInstanceID()
			Expect(err).NotTo(HaveOccurred())
			Expect(publicKey).To(Equal("fake-instance-id"))
		})
	})

	Describe("GetRegistryEndpoint", func() {
		var (
			ts          *httptest.Server
			registryURL *string
			dnsServer   *string
		)

		handlerFunc := func(w http.ResponseWriter, r *http.Request) {
			Expect(r.Method).To(Equal("GET"))
			Expect(r.URL.Path).To(Equal("/latest/user-data"))

			var jsonStr string

			if dnsServer == nil {
				jsonStr = fmt.Sprintf(`{"registry":{"endpoint":"%s"}}`, *registryURL)
			} else {
				jsonStr = fmt.Sprintf(`{
					"registry":{"endpoint":"%s"},
					"dns":{"nameserver":["%s"]}
				}`, *registryURL, *dnsServer)
			}

			w.Write([]byte(jsonStr))
		}

		BeforeEach(func() {
			url := "http://fake-registry.com"
			registryURL = &url
			dnsServer = nil

			handler := http.HandlerFunc(handlerFunc)
			ts = httptest.NewServer(handler)
			metadataService = NewConcreteMetadataService(ts.URL, dnsResolver)
		})

		AfterEach(func() {
			ts.Close()
		})

		Context("when metadata contains a dns server", func() {
			BeforeEach(func() {
				server := "fake-dns-server-ip"
				dnsServer = &server
			})

			Context("when registry endpoint is successfully resolved", func() {
				BeforeEach(func() {
					dnsResolver.RegisterRecord(fakeinf.FakeDNSRecord{
						DNSServers: []string{"fake-dns-server-ip"},
						Host:       "fake-registry.com",
						IP:         "fake-registry-ip",
					})
				})

				Context("when registry endpoint has a port", func() {
					BeforeEach(func() {
						url := "http://fake-registry.com:8877"
						registryURL = &url
					})

					It("returns the successfully resolved registry endpoint with port", func() {
						endpoint, err := metadataService.GetRegistryEndpoint()
						Expect(err).ToNot(HaveOccurred())
						Expect(endpoint).To(Equal("http://fake-registry-ip:8877"))
					})
				})

				Context("when registry endpoint does not have a port", func() {
					BeforeEach(func() {
						url := "http://fake-registry.com"
						registryURL = &url
					})

					It("returns the successfully resolved registry endpoint", func() {
						endpoint, err := metadataService.GetRegistryEndpoint()
						Expect(err).ToNot(HaveOccurred())
						Expect(endpoint).To(Equal("http://fake-registry-ip"))
					})
				})
			})

			Context("when registry endpoint is not successfully resolved", func() {
				BeforeEach(func() {
					dnsResolver.LookupHostErr = errors.New("fake-lookup-host-err")
				})

				It("returns error because it failed to resolve registry endpoint", func() {
					endpoint, err := metadataService.GetRegistryEndpoint()
					Expect(err).To(HaveOccurred())
					Expect(err.Error()).To(ContainSubstring("fake-lookup-host-err"))
					Expect(endpoint).To(BeEmpty())
				})
			})
		})

		Context("when metadata does not contain dns servers", func() {
			It("returns fetched registry endpoint", func() {
				endpoint, err := metadataService.GetRegistryEndpoint()
				Expect(err).NotTo(HaveOccurred())
				Expect(endpoint).To(Equal("http://fake-registry.com"))
			})
		})
	})
})
<|endoftext|>


<commit_before>package task

import (
	"log"

	"github.com/nzai/stockrecorder/crawl"
	"github.com/nzai/stockrecorder/market"
)

//	启动任务
func StartTasks() error {
	log.Print("启动任务")

	go func() {
		market.Add(market.America{})

		market.Monitor()
	}()

	//	启动抓取任务
	go crawl.Start()

	//	启动分析任务
	//	go analyse.StartJobs()

	return nil
}
<commit_msg>去除抓取指定股票的功能，增加中国股票市场的监视<commit_after>package task

import (
	"log"

	"github.com/nzai/stockrecorder/market"
)

//	启动任务
func StartTasks() error {
	log.Print("启动任务")

	go func() {
		//	美国股市
		market.Add(market.America{})
		//	中国股市
		market.Add(market.Chinese{})

		market.Monitor()
	}()

	//	启动分析任务
	//	go analyse.StartJobs()

	return nil
}
<|endoftext|>


<commit_before>/*
   DNS-over-HTTPS
   Copyright (C) 2017-2018 Star Brilliant <m13253@hotmail.com>

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/m13253/dns-over-https/json-dns"
	"github.com/miekg/dns"
	"golang.org/x/net/idna"
)

func (s *Server) parseRequestGoogle(w http.ResponseWriter, r *http.Request) *DNSRequest {
	name := r.FormValue("name")
	if name == "" {
		return &DNSRequest{
			errcode: 400,
			errtext: "Invalid argument value: \"name\"",
		}
	}
	if punycode, err := idna.ToASCII(name); err == nil {
		name = punycode
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"name\" = %q (%s)", name, err.Error()),
		}
	}

	rrTypeStr := r.FormValue("type")
	rrType := uint16(1)
	if rrTypeStr == "" {
	} else if v, err := strconv.ParseUint(rrTypeStr, 10, 16); err == nil {
		rrType = uint16(v)
	} else if v, ok := dns.StringToType[strings.ToUpper(rrTypeStr)]; ok {
		rrType = v
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"type\" = %q", rrTypeStr),
		}
	}

	cdStr := r.FormValue("cd")
	cd := false
	if cdStr == "1" || cdStr == "true" {
		cd = true
	} else if cdStr == "0" || cdStr == "false" || cdStr == "" {
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"cd\" = %q", cdStr),
		}
	}

	ednsClientSubnet := r.FormValue("edns_client_subnet")
	ednsClientFamily := uint16(0)
	ednsClientAddress := net.IP(nil)
	ednsClientNetmask := uint8(255)
	if ednsClientSubnet != "" {
		if ednsClientSubnet == "0/0" {
			ednsClientSubnet = "0.0.0.0/0"
		}
		slash := strings.IndexByte(ednsClientSubnet, '/')
		if slash < 0 {
			ednsClientAddress = net.ParseIP(ednsClientSubnet)
			if ednsClientAddress == nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
				ednsClientFamily = 1
				ednsClientAddress = ipv4
				ednsClientNetmask = 24
			} else {
				ednsClientFamily = 2
				ednsClientNetmask = 56
			}
		} else {
			ednsClientAddress = net.ParseIP(ednsClientSubnet[:slash])
			if ednsClientAddress == nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
				ednsClientFamily = 1
				ednsClientAddress = ipv4
			} else {
				ednsClientFamily = 2
			}
			netmask, err := strconv.ParseUint(ednsClientSubnet[slash+1:], 10, 8)
			if err != nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			ednsClientNetmask = uint8(netmask)
		}
	} else {
		ednsClientAddress = s.findClientIP(r)
		if ednsClientAddress == nil {
			ednsClientNetmask = 0
		} else if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
			ednsClientFamily = 1
			ednsClientAddress = ipv4
			ednsClientNetmask = 24
		} else {
			ednsClientFamily = 2
			ednsClientNetmask = 56
		}
	}

	msg := new(dns.Msg)
	msg.SetQuestion(dns.Fqdn(name), rrType)
	msg.CheckingDisabled = cd
	opt := new(dns.OPT)
	opt.Hdr.Name = "."
	opt.Hdr.Rrtype = dns.TypeOPT
	opt.SetUDPSize(dns.DefaultMsgSize)
	opt.SetDo(true)
	if ednsClientAddress != nil {
		edns0Subnet := new(dns.EDNS0_SUBNET)
		edns0Subnet.Code = dns.EDNS0SUBNET
		edns0Subnet.Family = ednsClientFamily
		edns0Subnet.SourceNetmask = ednsClientNetmask
		edns0Subnet.SourceScope = 0
		edns0Subnet.Address = ednsClientAddress
		opt.Option = append(opt.Option, edns0Subnet)
	}
	msg.Extra = append(msg.Extra, opt)

	return &DNSRequest{
		request:    msg,
		isTailored: ednsClientSubnet == "",
	}
}

func (s *Server) generateResponseGoogle(w http.ResponseWriter, r *http.Request, req *DNSRequest) {
	respJSON := jsonDNS.Marshal(req.response)
	respStr, err := json.Marshal(respJSON)
	if err != nil {
		log.Println(err)
		jsonDNS.FormatError(w, fmt.Sprintf("DNS packet parse failure (%s)", err.Error()), 500)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	now := time.Now().UTC().Format(http.TimeFormat)
	w.Header().Set("Date", now)
	w.Header().Set("Last-Modified", now)
	w.Header().Set("Vary", "Accept")
	if respJSON.HaveTTL {
		if req.isTailored {
			w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
		} else {
			w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
		}
		w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat))
	}
	if respJSON.Status == dns.RcodeServerFailure {
		w.WriteHeader(503)
	}
	w.Write(respStr)
}
<commit_msg>doh-server: change to google.go<commit_after>/*
   DNS-over-HTTPS
   Copyright (C) 2017-2018 Star Brilliant <m13253@hotmail.com>

   Permission is hereby granted, free of charge, to any person obtaining a
   copy of this software and associated documentation files (the "Software"),
   to deal in the Software without restriction, including without limitation
   the rights to use, copy, modify, merge, publish, distribute, sublicense,
   and/or sell copies of the Software, and to permit persons to whom the
   Software is furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in
   all copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
   DEALINGS IN THE SOFTWARE.
*/

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"

	"github.com/m13253/dns-over-https/json-dns"
	"github.com/miekg/dns"
	"golang.org/x/net/idna"
)

func (s *Server) parseRequestGoogle(w http.ResponseWriter, r *http.Request) *DNSRequest {
	name := r.FormValue("name")
	if name == "" {
		return &DNSRequest{
			errcode: 400,
			errtext: "Invalid argument value: \"name\"",
		}
	}
	if punycode, err := idna.ToASCII(name); err == nil {
		name = punycode
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"name\" = %q (%s)", name, err.Error()),
		}
	}

	rrTypeStr := r.FormValue("type")
	rrType := uint16(1)
	if rrTypeStr == "" {
	} else if v, err := strconv.ParseUint(rrTypeStr, 10, 16); err == nil {
		rrType = uint16(v)
	} else if v, ok := dns.StringToType[strings.ToUpper(rrTypeStr)]; ok {
		rrType = v
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"type\" = %q", rrTypeStr),
		}
	}

	cdStr := r.FormValue("cd")
	cd := false
	if cdStr == "1" || strings.ToUpper(cdStr) == "TRUE" {
		cd = true
	} else if cdStr == "0" || strings.ToUpper(cdStr) == "FALSE" || cdStr == "" {
	} else {
		return &DNSRequest{
			errcode: 400,
			errtext: fmt.Sprintf("Invalid argument value: \"cd\" = %q", cdStr),
		}
	}

	ednsClientSubnet := r.FormValue("edns_client_subnet")
	ednsClientFamily := uint16(0)
	ednsClientAddress := net.IP(nil)
	ednsClientNetmask := uint8(255)
	if ednsClientSubnet != "" {
		if ednsClientSubnet == "0/0" {
			ednsClientSubnet = "0.0.0.0/0"
		}
		slash := strings.IndexByte(ednsClientSubnet, '/')
		if slash < 0 {
			ednsClientAddress = net.ParseIP(ednsClientSubnet)
			if ednsClientAddress == nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
				ednsClientFamily = 1
				ednsClientAddress = ipv4
				ednsClientNetmask = 24
			} else {
				ednsClientFamily = 2
				ednsClientNetmask = 56
			}
		} else {
			ednsClientAddress = net.ParseIP(ednsClientSubnet[:slash])
			if ednsClientAddress == nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
				ednsClientFamily = 1
				ednsClientAddress = ipv4
			} else {
				ednsClientFamily = 2
			}
			netmask, err := strconv.ParseUint(ednsClientSubnet[slash+1:], 10, 8)
			if err != nil {
				return &DNSRequest{
					errcode: 400,
					errtext: fmt.Sprintf("Invalid argument value: \"edns_client_subnet\" = %q", ednsClientSubnet),
				}
			}
			ednsClientNetmask = uint8(netmask)
		}
	} else {
		ednsClientAddress = s.findClientIP(r)
		if ednsClientAddress == nil {
			ednsClientNetmask = 0
		} else if ipv4 := ednsClientAddress.To4(); ipv4 != nil {
			ednsClientFamily = 1
			ednsClientAddress = ipv4
			ednsClientNetmask = 24
		} else {
			ednsClientFamily = 2
			ednsClientNetmask = 56
		}
	}

	msg := new(dns.Msg)
	msg.SetQuestion(dns.Fqdn(name), rrType)
	msg.CheckingDisabled = cd
	opt := new(dns.OPT)
	opt.Hdr.Name = "."
	opt.Hdr.Rrtype = dns.TypeOPT
	opt.SetUDPSize(dns.DefaultMsgSize)
	opt.SetDo(true)
	if ednsClientAddress != nil {
		edns0Subnet := new(dns.EDNS0_SUBNET)
		edns0Subnet.Code = dns.EDNS0SUBNET
		edns0Subnet.Family = ednsClientFamily
		edns0Subnet.SourceNetmask = ednsClientNetmask
		edns0Subnet.SourceScope = 0
		edns0Subnet.Address = ednsClientAddress
		opt.Option = append(opt.Option, edns0Subnet)
	}
	msg.Extra = append(msg.Extra, opt)

	return &DNSRequest{
		request:    msg,
		isTailored: ednsClientSubnet == "",
	}
}

func (s *Server) generateResponseGoogle(w http.ResponseWriter, r *http.Request, req *DNSRequest) {
	respJSON := jsonDNS.Marshal(req.response)
	respStr, err := json.Marshal(respJSON)
	if err != nil {
		log.Println(err)
		jsonDNS.FormatError(w, fmt.Sprintf("DNS packet parse failure (%s)", err.Error()), 500)
		return
	}

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	now := time.Now().UTC().Format(http.TimeFormat)
	w.Header().Set("Date", now)
	w.Header().Set("Last-Modified", now)
	w.Header().Set("Vary", "Accept")
	if respJSON.HaveTTL {
		if req.isTailored {
			w.Header().Set("Cache-Control", "private, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
		} else {
			w.Header().Set("Cache-Control", "public, max-age="+strconv.Itoa(int(respJSON.LeastTTL)))
		}
		w.Header().Set("Expires", respJSON.EarliestExpires.Format(http.TimeFormat))
	}
	if respJSON.Status == dns.RcodeServerFailure {
		w.WriteHeader(503)
	}
	w.Write(respStr)
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"io/ioutil"

	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"
	"time"

	_ "github.com/mjibson/mog/codec/mpa"
	_ "github.com/mjibson/mog/codec/nsf"
	_ "github.com/mjibson/mog/protocol/file"
	_ "github.com/mjibson/mog/protocol/gmusic"
)

func TestServer(t *testing.T) {
	srv := New()
	ts := httptest.NewServer(srv.GetMux())
	defer ts.Close()
	client := &http.Client{Timeout: time.Second}
	fetch := func(path string, values url.Values) *http.Response {
		u := ts.URL + path + "?" + values.Encode()
		t.Log("fetching", u)
		resp, err := client.Get(u)
		if err != nil {
			t.Fatal(err)
		}
		if resp.StatusCode != 200 {
			b, _ := ioutil.ReadAll(resp.Body)
			t.Fatalf("%s: %s", resp.Status, string(b))
		}
		return resp
	}

	var resp *http.Response
	resp = fetch("/api/protocol/update", url.Values{
		"protocol": []string{"file"},
		"params":   []string{".."},
	})
	resp = fetch("/api/list", nil)
	if resp.StatusCode != 200 {
		t.Fatal("bad status")
	}
	songs := make([]string, 0)
	if err := json.NewDecoder(resp.Body).Decode(&songs); err != nil {
		t.Fatal(err)
	}
	if len(songs) == 0 {
		t.Fatal("expected songs")
	}
	v := url.Values{
		"add": []string{
			"file|1-../mm3.nsf",
			"file|2-../mm3.nsf",
			"file|3-../mm3.nsf",
			"file|4-../mm3.nsf",
		},
	}
	resp = fetch("/api/playlist/change", v)
	var pc PlaylistChange
	if err := json.NewDecoder(resp.Body).Decode(&pc); err != nil {
		t.Fatal(err)
	}
	resp = fetch("/api/cmd/play", nil)
	time.Sleep(time.Second * 2)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second * 2)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second * 2)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second * 2)
}
<commit_msg>Quicker<commit_after>package server

import (
	"encoding/json"
	"io/ioutil"

	"net/http"
	"net/http/httptest"
	"net/url"
	"testing"
	"time"

	_ "github.com/mjibson/mog/codec/mpa"
	_ "github.com/mjibson/mog/codec/nsf"
	_ "github.com/mjibson/mog/protocol/file"
	_ "github.com/mjibson/mog/protocol/gmusic"
)

func TestServer(t *testing.T) {
	srv := New()
	ts := httptest.NewServer(srv.GetMux())
	defer ts.Close()
	client := &http.Client{Timeout: time.Second}
	fetch := func(path string, values url.Values) *http.Response {
		u := ts.URL + path + "?" + values.Encode()
		t.Log("fetching", u)
		resp, err := client.Get(u)
		if err != nil {
			t.Fatal(err)
		}
		if resp.StatusCode != 200 {
			b, _ := ioutil.ReadAll(resp.Body)
			t.Fatalf("%s: %s", resp.Status, string(b))
		}
		return resp
	}

	var resp *http.Response
	resp = fetch("/api/protocol/update", url.Values{
		"protocol": []string{"file"},
		"params":   []string{".."},
	})
	resp = fetch("/api/list", nil)
	if resp.StatusCode != 200 {
		t.Fatal("bad status")
	}
	songs := make([]string, 0)
	if err := json.NewDecoder(resp.Body).Decode(&songs); err != nil {
		t.Fatal(err)
	}
	if len(songs) == 0 {
		t.Fatal("expected songs")
	}
	v := url.Values{
		"add": []string{
			"file|1-../mm3.nsf",
			"file|2-../mm3.nsf",
			"file|3-../mm3.nsf",
			"file|4-../mm3.nsf",
		},
	}
	resp = fetch("/api/playlist/change", v)
	var pc PlaylistChange
	if err := json.NewDecoder(resp.Body).Decode(&pc); err != nil {
		t.Fatal(err)
	}
	resp = fetch("/api/cmd/play", nil)
	time.Sleep(time.Second)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second)
	resp = fetch("/api/cmd/next", nil)
	time.Sleep(time.Second)
}
<|endoftext|>


<commit_before>package server

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/gamegos/scotty/storage"
)

var appID = "testapp"
var channelID = "someRandomchannelID"
var initialData = `{
		"id": "` + appID + `",
		"gcm": {
				"projectId": "projectid",
				"apiKey": "apikey"
		}
}`
var updatedData = `
{
		"id": "` + appID + `",
		"gcm": {
				"projectId": "updatedprojectid",
				"apiKey": "updatedapikey"
		}
}`

type jsonResponse struct {
	Status  string          `json:"status"`
	Data    json.RawMessage `json:"data,omitempty"`
	Message string          `json:"message,omitempty"`
}

var (
	testServer *Server
)

func init() {
	stg := storage.NewMemStorage()
	testServer = Init(stg)
}

func apiCall(method string, urlStr string, bodyStr string) (*httptest.ResponseRecorder, error) {
	req, err := http.NewRequest(method, urlStr, strings.NewReader(bodyStr))

	if err != nil {
		return nil, err
	}

	w := httptest.NewRecorder()
	testServer.router.ServeHTTP(w, req)

	return w, nil
}

func TestCreateApp(t *testing.T) {
	postBody := initialData
	res, err := apiCall("POST", "/apps", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("App could not be created.", res.Code, res.Body)
	}
}

func TestUpdateApp(t *testing.T) {
	postBody := updatedData
	res, err := apiCall("PUT", "/apps/"+appID, postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusOK {
		t.Error("App could not be updated.")
	}
}

func TestGetApp(t *testing.T) {
	res, err := apiCall("GET", "/apps/"+appID, "")

	if err != nil {
		t.Error(err)
	}

	var response jsonResponse

	decoder := json.NewDecoder(res.Body)

	if err := decoder.Decode(&response); err != nil {
		t.Error(err)
		return
	}

	var app storage.App

	decoder = json.NewDecoder(strings.NewReader(updatedData))

	if err := decoder.Decode(&app); err != nil {
		t.Error(err)
		return
	}

	updatedAppStr, _ := json.Marshal(app)

	if string(response.Data) != string(updatedAppStr) {
		t.Error("Received app data is not the same as updated data.")
	}
}

func TestAddDevice(t *testing.T) {
	postBody := `{"subscriberId": "randomSubId", "platform": "gcm", "token": "foo123"}`
	res, err := apiCall("POST", "/apps/"+appID+"/devices", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Subscriber device could not be added.")
	}
}

func TestAddChannel(t *testing.T) {
	postBody := `{"id": "` + channelID + `"}`
	res, err := apiCall("POST", "/apps/"+appID+"/channels", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Channel could not be added.")
	}
}

func TestAddSubscriber(t *testing.T) {
	postBody := `{"subscribers": ["foo", "bar"]}`
	res, err := apiCall("POST", "/apps/"+appID+"/channels/"+channelID+"/subscribers", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Subscriber device could not be added.")
	}
}

func TestDeleteChannel(t *testing.T) {
	res, err := apiCall("DELETE", "/apps/"+appID+"/channels/"+channelID, "")

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusOK {
		t.Error("Channel could not be deleted.")
	}
}
<commit_msg>Fix server test<commit_after>package server

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"strings"
	"testing"

	"github.com/gamegos/scotty/storage"
	memstorage "github.com/gamegos/scotty/storage/drivers/memory"
)

var appID = "testapp"
var channelID = "someRandomchannelID"
var initialData = `{
		"id": "` + appID + `",
		"gcm": {
				"projectId": "projectid",
				"apiKey": "apikey"
		}
}`
var updatedData = `
{
		"id": "` + appID + `",
		"gcm": {
				"projectId": "updatedprojectid",
				"apiKey": "updatedapikey"
		}
}`

type jsonResponse struct {
	Status  string          `json:"status"`
	Data    json.RawMessage `json:"data,omitempty"`
	Message string          `json:"message,omitempty"`
}

var (
	testServer *Server
)

func init() {
	stg := memstorage.New()
	testServer = Init(stg)
}

func apiCall(method string, urlStr string, bodyStr string) (*httptest.ResponseRecorder, error) {
	req, err := http.NewRequest(method, urlStr, strings.NewReader(bodyStr))

	if err != nil {
		return nil, err
	}

	w := httptest.NewRecorder()
	testServer.router.ServeHTTP(w, req)

	return w, nil
}

func TestCreateApp(t *testing.T) {
	postBody := initialData
	res, err := apiCall("POST", "/apps", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("App could not be created.", res.Code, res.Body)
	}
}

func TestUpdateApp(t *testing.T) {
	postBody := updatedData
	res, err := apiCall("PUT", "/apps/"+appID, postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusOK {
		t.Error("App could not be updated.")
	}
}

func TestGetApp(t *testing.T) {
	res, err := apiCall("GET", "/apps/"+appID, "")

	if err != nil {
		t.Error(err)
	}

	var response jsonResponse

	decoder := json.NewDecoder(res.Body)

	if err := decoder.Decode(&response); err != nil {
		t.Error(err)
		return
	}

	var app storage.App

	decoder = json.NewDecoder(strings.NewReader(updatedData))

	if err := decoder.Decode(&app); err != nil {
		t.Error(err)
		return
	}

	updatedAppStr, _ := json.Marshal(app)

	if string(response.Data) != string(updatedAppStr) {
		t.Error("Received app data is not the same as updated data.")
	}
}

func TestAddDevice(t *testing.T) {
	postBody := `{"subscriberId": "randomSubId", "platform": "gcm", "token": "foo123"}`
	res, err := apiCall("POST", "/apps/"+appID+"/devices", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Subscriber device could not be added.")
	}
}

func TestAddChannel(t *testing.T) {
	postBody := `{"id": "` + channelID + `"}`
	res, err := apiCall("POST", "/apps/"+appID+"/channels", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Channel could not be added.")
	}
}

func TestAddSubscriber(t *testing.T) {
	postBody := `{"subscribers": ["foo", "bar"]}`
	res, err := apiCall("POST", "/apps/"+appID+"/channels/"+channelID+"/subscribers", postBody)

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusCreated {
		t.Error("Subscriber device could not be added.")
	}
}

func TestDeleteChannel(t *testing.T) {
	res, err := apiCall("DELETE", "/apps/"+appID+"/channels/"+channelID, "")

	if err != nil {
		t.Error(err)
	}

	if res.Code != http.StatusOK {
		t.Error("Channel could not be deleted.")
	}
}
<|endoftext|>


<commit_before>package lua

import (
	"github.com/loadimpact/speedboat/runner"
	"github.com/valyala/fasthttp"
	"github.com/yuin/gopher-lua"
	"golang.org/x/net/context"
	"math"
	"time"
)

type LuaRunner struct {
	Filename string
	Source   string
	Client   *fasthttp.Client
}

type VUContext struct {
	r   *LuaRunner
	ctx context.Context
	ch  chan runner.Result
}

func New(filename, src string) *LuaRunner {
	return &LuaRunner{
		Filename: filename,
		Source:   src,
		Client: &fasthttp.Client{
			MaxIdleConnDuration: time.Duration(0),
			MaxConnsPerHost:     math.MaxInt64,
		},
	}
}

func (r *LuaRunner) Run(ctx context.Context, id int64) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		vu := VUContext{r: r, ctx: ctx, ch: ch}

		L := lua.NewState()
		defer L.Close()

		L.SetGlobal("__id", lua.LNumber(id))

		L.SetGlobal("sleep", L.NewFunction(vu.Sleep))

		L.PreloadModule("http", vu.HTTPLoader)

		// Try to load the script, abort execution if it fails
		lfn, err := L.LoadString(r.Source)
		if err != nil {
			ch <- runner.Result{Error: err}
			return
		}

		for {
			L.Push(lfn)
			if err := L.PCall(0, 0, nil); err != nil {
				ch <- runner.Result{Error: err}
			}

			select {
			case <-ctx.Done():
				return
			default:
			}
		}
	}()

	return ch
}
<commit_msg>Should give us unlimited TCP timeout<commit_after>package lua

import (
	"github.com/loadimpact/speedboat/runner"
	"github.com/valyala/fasthttp"
	"github.com/yuin/gopher-lua"
	"golang.org/x/net/context"
	"math"
	"time"
)

type LuaRunner struct {
	Filename string
	Source   string
	Client   *fasthttp.Client
}

type VUContext struct {
	r   *LuaRunner
	ctx context.Context
	ch  chan runner.Result
}

func New(filename, src string) *LuaRunner {
	return &LuaRunner{
		Filename: filename,
		Source:   src,
		Client: &fasthttp.Client{
			Dial:                fasthttp.Dial,
			MaxIdleConnDuration: time.Duration(0),
			MaxConnsPerHost:     math.MaxInt64,
		},
	}
}

func (r *LuaRunner) Run(ctx context.Context, id int64) <-chan runner.Result {
	ch := make(chan runner.Result)

	go func() {
		defer close(ch)

		vu := VUContext{r: r, ctx: ctx, ch: ch}

		L := lua.NewState()
		defer L.Close()

		L.SetGlobal("__id", lua.LNumber(id))

		L.SetGlobal("sleep", L.NewFunction(vu.Sleep))

		L.PreloadModule("http", vu.HTTPLoader)

		// Try to load the script, abort execution if it fails
		lfn, err := L.LoadString(r.Source)
		if err != nil {
			ch <- runner.Result{Error: err}
			return
		}

		for {
			L.Push(lfn)
			if err := L.PCall(0, 0, nil); err != nil {
				ch <- runner.Result{Error: err}
			}

			select {
			case <-ctx.Done():
				return
			default:
			}
		}
	}()

	return ch
}
<|endoftext|>


<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package service_test

import (
	"path/filepath"
	"runtime"
	"strings"

	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils/shell"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/juju/osenv"
	"github.com/juju/juju/service"
	"github.com/juju/juju/service/common"
)

func init() {
	quote = "'"
	if runtime.GOOS == "windows" {
		cmdSuffix = ".exe"
	}
}

var quote, cmdSuffix string

type agentSuite struct {
	service.BaseSuite
}

var _ = gc.Suite(&agentSuite{})

func (*agentSuite) TestAgentConfMachineLocal(c *gc.C) {
	// We use two distinct directories to ensure the paths don't get
	// mixed up during the call.
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		quote + filepath.Join(dataDir, "tools", "machine-0", "jujud"+cmdSuffix) + quote,
		"machine",
		"--data-dir", quote + dataDir + quote,
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "machine-0.log"),
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfMachineUbuntu(c *gc.C) {
	dataDir := "/var/lib/juju"
	logDir := "/var/log/juju"
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("ubuntu")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		"'" + dataDir + "/tools/machine-0/jujud'",
		"machine",
		"--data-dir", "'" + dataDir + "'",
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   logDir + "/machine-0.log",
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfMachineWindows(c *gc.C) {
	dataDir := `C:\Juju\lib\juju`
	logDir := `C:\Juju\logs\juju`
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("windows")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		`'` + dataDir + `\tools\machine-0\jujud.exe'`,
		"machine",
		"--data-dir", `'` + dataDir + `'`,
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   logDir + `\machine-0.log`,
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfUnit(c *gc.C) {
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewUnitAgentInfo("wordpress/0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		quote + filepath.Join(dataDir, "tools", "unit-wordpress-0", "jujud"+cmdSuffix) + quote,
		"unit",
		"--data-dir", quote + dataDir + quote,
		"--unit-name", "wordpress/0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju unit agent for wordpress/0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "unit-wordpress-0.log"),
		Env:       osenv.FeatureFlags(),
		Timeout:   300,
	})
}

func (*agentSuite) TestContainerAgentConf(c *gc.C) {
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewUnitAgentInfo("wordpress/0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.ContainerAgentConf(info, renderer, "cont")

	cmd := strings.Join([]string{
		quote + filepath.Join(dataDir, "tools", "unit-wordpress-0", "jujud"+cmdSuffix) + quote,
		"unit",
		"--data-dir", quote + dataDir + quote,
		"--unit-name", "wordpress/0",
		"--debug",
	}, " ")
	env := osenv.FeatureFlags()
	env[osenv.JujuContainerTypeEnvKey] = "cont"
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju unit agent for wordpress/0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "unit-wordpress-0.log"),
		Env:       env,
		Timeout:   300,
	})
}

func (*agentSuite) TestShutdownAfterConf(c *gc.C) {
	conf, err := service.ShutdownAfterConf("spam")
	c.Assert(err, jc.ErrorIsNil)

	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:         "juju shutdown job",
		Transient:    true,
		AfterStopped: "spam",
		ExecStart:    "/sbin/shutdown -h now",
	})
	renderer := &shell.BashRenderer{}
	c.Check(conf.Validate(renderer), jc.ErrorIsNil)
}

func (*agentSuite) TestShutdownAfterConfMissingServiceName(c *gc.C) {
	_, err := service.ShutdownAfterConf("")

	c.Check(err, gc.ErrorMatches, `.*missing "after" service name.*`)
}
<commit_msg>Use utils.ShQuote instead of manually adding single quotes.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package service_test

import (
	"path/filepath"
	"runtime"
	"strings"

	jc "github.com/juju/testing/checkers"
	"github.com/juju/utils"
	"github.com/juju/utils/shell"
	gc "gopkg.in/check.v1"

	"github.com/juju/juju/juju/osenv"
	"github.com/juju/juju/service"
	"github.com/juju/juju/service/common"
)

var (
	cmdSuffix string
	shquote   = utils.ShQuote
)

func init() {
	if runtime.GOOS == "windows" {
		cmdSuffix = ".exe"
	}
}

type agentSuite struct {
	service.BaseSuite
}

var _ = gc.Suite(&agentSuite{})

func (*agentSuite) TestAgentConfMachineLocal(c *gc.C) {
	// We use two distinct directories to ensure the paths don't get
	// mixed up during the call.
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	jujud := filepath.Join(dataDir, "tools", "machine-0", "jujud"+cmdSuffix)
	cmd := strings.Join([]string{
		shquote(jujud),
		"machine",
		"--data-dir", shquote(dataDir),
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "machine-0.log"),
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfMachineUbuntu(c *gc.C) {
	dataDir := "/var/lib/juju"
	logDir := "/var/log/juju"
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("ubuntu")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		shquote(dataDir + "/tools/machine-0/jujud"),
		"machine",
		"--data-dir", shquote(dataDir),
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   logDir + "/machine-0.log",
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfMachineWindows(c *gc.C) {
	dataDir := `C:\Juju\lib\juju`
	logDir := `C:\Juju\logs\juju`
	info := service.NewMachineAgentInfo("0", dataDir, logDir)
	renderer, err := shell.NewRenderer("windows")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	cmd := strings.Join([]string{
		shquote(dataDir + `\tools\machine-0\jujud.exe`),
		"machine",
		"--data-dir", shquote(dataDir),
		"--machine-id", "0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju agent for machine-0",
		ExecStart: cmd,
		Logfile:   logDir + `\machine-0.log`,
		Env:       osenv.FeatureFlags(),
		Limit: map[string]int{
			"nofile": 20000,
		},
		Timeout: 300,
	})
}

func (*agentSuite) TestAgentConfUnit(c *gc.C) {
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewUnitAgentInfo("wordpress/0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.AgentConf(info, renderer)

	jujud := filepath.Join(dataDir, "tools", "unit-wordpress-0", "jujud"+cmdSuffix)
	cmd := strings.Join([]string{
		shquote(jujud),
		"unit",
		"--data-dir", shquote(dataDir),
		"--unit-name", "wordpress/0",
		"--debug",
	}, " ")
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju unit agent for wordpress/0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "unit-wordpress-0.log"),
		Env:       osenv.FeatureFlags(),
		Timeout:   300,
	})
}

func (*agentSuite) TestContainerAgentConf(c *gc.C) {
	dataDir := c.MkDir()
	logDir := c.MkDir()
	info := service.NewUnitAgentInfo("wordpress/0", dataDir, logDir)
	renderer, err := shell.NewRenderer("")
	c.Assert(err, jc.ErrorIsNil)
	conf := service.ContainerAgentConf(info, renderer, "cont")

	jujud := filepath.Join(dataDir, "tools", "unit-wordpress-0", "jujud"+cmdSuffix)
	cmd := strings.Join([]string{
		shquote(jujud),
		"unit",
		"--data-dir", shquote(dataDir),
		"--unit-name", "wordpress/0",
		"--debug",
	}, " ")
	env := osenv.FeatureFlags()
	env[osenv.JujuContainerTypeEnvKey] = "cont"
	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:      "juju unit agent for wordpress/0",
		ExecStart: cmd,
		Logfile:   filepath.Join(logDir, "unit-wordpress-0.log"),
		Env:       env,
		Timeout:   300,
	})
}

func (*agentSuite) TestShutdownAfterConf(c *gc.C) {
	conf, err := service.ShutdownAfterConf("spam")
	c.Assert(err, jc.ErrorIsNil)

	c.Check(conf, jc.DeepEquals, common.Conf{
		Desc:         "juju shutdown job",
		Transient:    true,
		AfterStopped: "spam",
		ExecStart:    "/sbin/shutdown -h now",
	})
	renderer := &shell.BashRenderer{}
	c.Check(conf.Validate(renderer), jc.ErrorIsNil)
}

func (*agentSuite) TestShutdownAfterConfMissingServiceName(c *gc.C) {
	_, err := service.ShutdownAfterConf("")

	c.Check(err, gc.ErrorMatches, `.*missing "after" service name.*`)
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Kubernetes Authors.

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 model

import (
	"fmt"
	"net"
	"strings"

	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
	"k8s.io/kops/util/pkg/distributions"
)

// SysctlBuilder set up our sysctls
type SysctlBuilder struct {
	*NodeupModelContext
}

var _ fi.ModelBuilder = &SysctlBuilder{}

// Build is responsible for configuring sysctl settings
func (b *SysctlBuilder) Build(c *fi.ModelBuilderContext) error {
	var sysctls []string

	// Common settings
	{
		sysctls = append(sysctls,
			"# Kubernetes Settings",
			"")

		// A higher vm.max_map_count is great for elasticsearch, mongo, or other mmap users
		// See https://github.com/kubernetes/kops/issues/1340
		sysctls = append(sysctls, "vm.max_map_count = 262144",
			"")

		// See https://github.com/kubernetes/kubernetes/pull/38001
		sysctls = append(sysctls,
			"kernel.softlockup_panic = 1",
			"kernel.softlockup_all_cpu_backtrace = 1",
			"")

		// See https://github.com/kubernetes/kops/issues/6342
		portRange := b.Cluster.Spec.KubeAPIServer.ServiceNodePortRange
		if portRange == "" {
			portRange = "30000-32767" // Default kube-apiserver ServiceNodePortRange
		}
		sysctls = append(sysctls, "net.ipv4.ip_local_reserved_ports = "+portRange,
			"")

		// See https://github.com/kubernetes/kube-deploy/issues/261
		// and https://github.com/kubernetes/kops/issues/10206
		sysctls = append(sysctls,
			"# Increase the number of connections",
			"net.core.somaxconn = 32768",
			"",

			"# Maximum Socket Receive Buffer",
			"net.core.rmem_max = 16777216",
			"",

			"# Maximum Socket Send Buffer",
			"net.core.wmem_max = 16777216",
			"",

			"# Increase the maximum total buffer-space allocatable",
			"net.ipv4.tcp_wmem = 4096 87380 16777216",
			"net.ipv4.tcp_rmem = 4096 87380 16777216",
			"",

			"# Increase the number of outstanding syn requests allowed",
			"net.ipv4.tcp_max_syn_backlog = 8096",
			"",

			"# For persistent HTTP connections",
			"net.ipv4.tcp_slow_start_after_idle = 0",
			"",

			"# Allow to reuse TIME_WAIT sockets for new connections",
			"# when it is safe from protocol viewpoint",
			"net.ipv4.tcp_tw_reuse = 1",
			"",

			// We can't change the local_port_range without changing the NodePort range
			//"# Allowed local port range",
			//"net.ipv4.ip_local_port_range = 10240 65535",
			//"",

			"# Max number of packets that can be queued on interface input",
			"# If kernel is receiving packets faster than can be processed",
			"# this queue increases",
			"net.core.netdev_max_backlog = 16384",
			"",

			"# Increase size of file handles and inode cache",
			"fs.file-max = 2097152",
			"",

			"# Max number of inotify instances and watches for a user",
			"# Since dockerd runs as a single user, the default instances value of 128 per user is too low",
			"# e.g. uses of inotify: nginx ingress controller, kubectl logs -f",
			"fs.inotify.max_user_instances = 8192",
			"fs.inotify.max_user_watches = 524288",

			"# Additional sysctl flags that kubelet expects",
			"vm.overcommit_memory = 1",
			"kernel.panic = 10",
			"kernel.panic_on_oops = 1",
			"",
		)
	}

	if b.CloudProvider == kops.CloudProviderAWS {
		sysctls = append(sysctls,
			"# AWS settings",
			"",
			"# Issue #23395",
			"net.ipv4.neigh.default.gc_thresh1=0",
			"")
	}

	// Running Flannel on Amazon Linux 2 needs custom settings
	if b.Cluster.Spec.Networking.Flannel != nil && b.Distribution == distributions.DistributionAmazonLinux2 {
		proxyMode := b.Cluster.Spec.KubeProxy.ProxyMode
		if proxyMode == "" || proxyMode == "iptables" {
			sysctls = append(sysctls,
				"# Flannel settings on Amazon Linux 2",
				"# Issue https://github.com/coreos/flannel/issues/902",
				"net.bridge.bridge-nf-call-ip6tables=1",
				"net.bridge.bridge-nf-call-iptables=1",
				"")
		}
	}

	if b.Cluster.Spec.IsIPv6Only() {
		if b.Distribution == distributions.DistributionDebian11 {
			// Accepting Router Advertisements must be enabled for each existing network interface to take effect.
			// net.ipv6.conf.all.accept_ra takes effect only for newly created network interfaces.
			// https://bugzilla.kernel.org/show_bug.cgi?id=11655
			sysctls = append(sysctls, "# Enable Router Advertisements to get the default IPv6 route")
			ifaces, err := net.Interfaces()
			if err != nil {
				return err
			}
			for _, iface := range ifaces {
				// Accept Router Advertisements for ethernet network interfaces with slot position.
				// https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html
				if strings.HasPrefix(iface.Name, "ens") {
					sysctls = append(sysctls, fmt.Sprintf("net.ipv6.conf.%s.accept_ra=2", iface.Name))
				}
			}
		}
		sysctls = append(sysctls,
			"# Enable IPv6 forwarding for network plugins that don't do it themselves",
			"net.ipv6.conf.all.forwarding=1",
			"")
	} else {
		sysctls = append(sysctls,
			"# Prevent docker from changing iptables: https://github.com/kubernetes/kubernetes/issues/40182",
			"net.ipv4.ip_forward=1",
			"")
	}

	if b.Cluster.Spec.Networking.Cilium != nil {
		sysctls = append(sysctls,
			"# Depending on systemd version, cloud and distro, rp_filters may be enabled.",
			"# Cilium requires this to be disabled. See https://github.com/cilium/cilium/issues/10645",
			"net.ipv4.conf.all.rp_filter=0",
			"")
	}

	if params := b.NodeupConfig.SysctlParameters; len(params) > 0 {
		sysctls = append(sysctls,
			"# Custom sysctl parameters from instance group spec",
			"")
		for _, param := range params {
			if !strings.ContainsRune(param, '=') {
				return fmt.Errorf("invalid SysctlParameter: expected %q to contain '='", param)
			}
			sysctls = append(sysctls, param)
		}
	}

	if params := b.Cluster.Spec.SysctlParameters; len(params) > 0 {
		sysctls = append(sysctls,
			"# Custom sysctl parameters from cluster spec",
			"")
		for _, param := range params {
			if !strings.ContainsRune(param, '=') {
				return fmt.Errorf("invalid SysctlParameter: expected %q to contain '='", param)
			}
			sysctls = append(sysctls, param)
		}
	}

	c.AddTask(&nodetasks.File{
		Path:            "/etc/sysctl.d/99-k8s-general.conf",
		Contents:        fi.NewStringResource(strings.Join(sysctls, "\n")),
		Type:            nodetasks.FileType_File,
		OnChangeExecute: [][]string{{"sysctl", "--system"}},
	})

	return nil
}
<commit_msg>Disable rp_filter on cilium hosts<commit_after>/*
Copyright 2019 The Kubernetes Authors.

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 model

import (
	"fmt"
	"net"
	"strings"

	"k8s.io/kops/pkg/apis/kops"
	"k8s.io/kops/upup/pkg/fi"
	"k8s.io/kops/upup/pkg/fi/nodeup/nodetasks"
	"k8s.io/kops/util/pkg/distributions"
)

// SysctlBuilder set up our sysctls
type SysctlBuilder struct {
	*NodeupModelContext
}

var _ fi.ModelBuilder = &SysctlBuilder{}

// Build is responsible for configuring sysctl settings
func (b *SysctlBuilder) Build(c *fi.ModelBuilderContext) error {
	var sysctls []string

	// Common settings
	{
		sysctls = append(sysctls,
			"# Kubernetes Settings",
			"")

		// A higher vm.max_map_count is great for elasticsearch, mongo, or other mmap users
		// See https://github.com/kubernetes/kops/issues/1340
		sysctls = append(sysctls, "vm.max_map_count = 262144",
			"")

		// See https://github.com/kubernetes/kubernetes/pull/38001
		sysctls = append(sysctls,
			"kernel.softlockup_panic = 1",
			"kernel.softlockup_all_cpu_backtrace = 1",
			"")

		// See https://github.com/kubernetes/kops/issues/6342
		portRange := b.Cluster.Spec.KubeAPIServer.ServiceNodePortRange
		if portRange == "" {
			portRange = "30000-32767" // Default kube-apiserver ServiceNodePortRange
		}
		sysctls = append(sysctls, "net.ipv4.ip_local_reserved_ports = "+portRange,
			"")

		// See https://github.com/kubernetes/kube-deploy/issues/261
		// and https://github.com/kubernetes/kops/issues/10206
		sysctls = append(sysctls,
			"# Increase the number of connections",
			"net.core.somaxconn = 32768",
			"",

			"# Maximum Socket Receive Buffer",
			"net.core.rmem_max = 16777216",
			"",

			"# Maximum Socket Send Buffer",
			"net.core.wmem_max = 16777216",
			"",

			"# Increase the maximum total buffer-space allocatable",
			"net.ipv4.tcp_wmem = 4096 87380 16777216",
			"net.ipv4.tcp_rmem = 4096 87380 16777216",
			"",

			"# Increase the number of outstanding syn requests allowed",
			"net.ipv4.tcp_max_syn_backlog = 8096",
			"",

			"# For persistent HTTP connections",
			"net.ipv4.tcp_slow_start_after_idle = 0",
			"",

			"# Allow to reuse TIME_WAIT sockets for new connections",
			"# when it is safe from protocol viewpoint",
			"net.ipv4.tcp_tw_reuse = 1",
			"",

			// We can't change the local_port_range without changing the NodePort range
			//"# Allowed local port range",
			//"net.ipv4.ip_local_port_range = 10240 65535",
			//"",

			"# Max number of packets that can be queued on interface input",
			"# If kernel is receiving packets faster than can be processed",
			"# this queue increases",
			"net.core.netdev_max_backlog = 16384",
			"",

			"# Increase size of file handles and inode cache",
			"fs.file-max = 2097152",
			"",

			"# Max number of inotify instances and watches for a user",
			"# Since dockerd runs as a single user, the default instances value of 128 per user is too low",
			"# e.g. uses of inotify: nginx ingress controller, kubectl logs -f",
			"fs.inotify.max_user_instances = 8192",
			"fs.inotify.max_user_watches = 524288",

			"# Additional sysctl flags that kubelet expects",
			"vm.overcommit_memory = 1",
			"kernel.panic = 10",
			"kernel.panic_on_oops = 1",
			"",
		)
	}

	if b.CloudProvider == kops.CloudProviderAWS {
		sysctls = append(sysctls,
			"# AWS settings",
			"",
			"# Issue #23395",
			"net.ipv4.neigh.default.gc_thresh1=0",
			"")
	}

	// Running Flannel on Amazon Linux 2 needs custom settings
	if b.Cluster.Spec.Networking.Flannel != nil && b.Distribution == distributions.DistributionAmazonLinux2 {
		proxyMode := b.Cluster.Spec.KubeProxy.ProxyMode
		if proxyMode == "" || proxyMode == "iptables" {
			sysctls = append(sysctls,
				"# Flannel settings on Amazon Linux 2",
				"# Issue https://github.com/coreos/flannel/issues/902",
				"net.bridge.bridge-nf-call-ip6tables=1",
				"net.bridge.bridge-nf-call-iptables=1",
				"")
		}
	}

	if b.Cluster.Spec.IsIPv6Only() {
		if b.Distribution == distributions.DistributionDebian11 {
			// Accepting Router Advertisements must be enabled for each existing network interface to take effect.
			// net.ipv6.conf.all.accept_ra takes effect only for newly created network interfaces.
			// https://bugzilla.kernel.org/show_bug.cgi?id=11655
			sysctls = append(sysctls, "# Enable Router Advertisements to get the default IPv6 route")
			ifaces, err := net.Interfaces()
			if err != nil {
				return err
			}
			for _, iface := range ifaces {
				// Accept Router Advertisements for ethernet network interfaces with slot position.
				// https://www.freedesktop.org/software/systemd/man/systemd.net-naming-scheme.html
				if strings.HasPrefix(iface.Name, "ens") {
					sysctls = append(sysctls, fmt.Sprintf("net.ipv6.conf.%s.accept_ra=2", iface.Name))
				}
			}
		}
		sysctls = append(sysctls,
			"# Enable IPv6 forwarding for network plugins that don't do it themselves",
			"net.ipv6.conf.all.forwarding=1",
			"")
	} else {
		sysctls = append(sysctls,
			"# Prevent docker from changing iptables: https://github.com/kubernetes/kubernetes/issues/40182",
			"net.ipv4.ip_forward=1",
			"")
	}

	if b.Cluster.Spec.Networking.Cilium != nil {
		sysctls = append(sysctls,
			"# Depending on systemd version, cloud and distro, rp_filters may be enabled.",
			"# Cilium requires this to be disabled. See https://github.com/cilium/cilium/issues/10645",
			"net.ipv4.conf.all.rp_filter=0",
			"net.ipv4.conf.lxc*.rp_filter=0",
			"net.ipv4.conf.cilium_*.rp_filter=0",
			"")
	}

	if params := b.NodeupConfig.SysctlParameters; len(params) > 0 {
		sysctls = append(sysctls,
			"# Custom sysctl parameters from instance group spec",
			"")
		for _, param := range params {
			if !strings.ContainsRune(param, '=') {
				return fmt.Errorf("invalid SysctlParameter: expected %q to contain '='", param)
			}
			sysctls = append(sysctls, param)
		}
	}

	if params := b.Cluster.Spec.SysctlParameters; len(params) > 0 {
		sysctls = append(sysctls,
			"# Custom sysctl parameters from cluster spec",
			"")
		for _, param := range params {
			if !strings.ContainsRune(param, '=') {
				return fmt.Errorf("invalid SysctlParameter: expected %q to contain '='", param)
			}
			sysctls = append(sysctls, param)
		}
	}

	c.AddTask(&nodetasks.File{
		Path:            "/etc/sysctl.d/99-k8s-general.conf",
		Contents:        fi.NewStringResource(strings.Join(sysctls, "\n")),
		Type:            nodetasks.FileType_File,
		OnChangeExecute: [][]string{{"sysctl", "--system"}},
	})

	return nil
}
<|endoftext|>


<commit_before>// Copyright 2014 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package templates

import (
	"fmt"
)

var masterTemplate = fmt.Sprintf(`<!DOCTYPE HTML>

	<base href="{{ .BaseUrl }}">

	<title>{{.PageTitle}}</title>
	<meta name="description" content="{{.Description}}">

	<link rel="search" type="application/opensearchdescription+xml" title="{{.RepositoryName}}" href="/opensearch.xml" />

	<link rel="canonical" href="{{.BaseUrl}}">
	<link rel="alternate" hreflang="{{.LanguageTag}}" href="{{.BaseUrl}}">
	<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed.rss">
	<link rel="shortcut icon" href="/theme/favicon.ico">

	<link rel="stylesheet" href="/theme/screen.css" media="screen">
	<link rel="stylesheet" href="/theme/print.css" media="print">
	<link rel="stylesheet" href="/theme/codehighlighting/highlight.css" media="screen, print">

{{ if .ToplevelNavigation}}

	{{range .ToplevelNavigation.Entries}}

		{{.Title}}

	{{end}}

{{end}}

	<form action="/search" method="GET">
		<input class="typeahead" type="text" name="q" placeholder="search" autocomplete="off">
		<input type="submit" style="visibility:hidden; position: fixed;"/>
	</form>

{{ if .BreadcrumbNavigation}}

	{{range .BreadcrumbNavigation.Entries}}
		{{.Title}}{{if not .IsLast}} » {{end}}
	{{end}}

{{end}}

%s

	{{if .ItemNavigation}}

			{{if .ItemNavigation.Parent}}
			↑ Parent
			{{end}}

			{{if .ItemNavigation.Previous}}
			← Previous
			{{end}}

			{{if .ItemNavigation.Next}}
			Next →
			{{end}}

	{{end}}

	{{ if .Childs }}

Childs

	{{range .Childs}}

		{{.Title}}

{{.Description}}

	{{end}}

	{{end}}

	{{if .TagCloud}}

Tag Cloud

		{{range .TagCloud}}

			{{.Name}}

		{{end}}

	{{end}}

{{if or .PrintUrl .JsonUrl .RtfUrl}}

	{{if .PrintUrl}}
Print
{{end}}
	{{if .JsonUrl}}
JSON
{{end}}
	{{if .RtfUrl}}
Rich Text
{{end}}

{{end}}

Search

Tags

Sitemap

RSS Feed

{{ if .IsRepositoryItem }}

{{ end }}

{{if .Analytics.Enabled}}
{{if .Analytics.GoogleAnalytics.Enabled}}

{{end}}
{{end}}

`, ChildTemplatePlaceholder)
<commit_msg>Reintroduced the geo location meta tags<commit_after>// Copyright 2014 Andreas Koch. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package templates

import (
	"fmt"
)

var masterTemplate = fmt.Sprintf(`<!DOCTYPE HTML>

	<base href="{{ .BaseUrl }}">

	<title>{{.PageTitle}}</title>
	<meta name="description" content="{{.Description}}">

	<link rel="search" type="application/opensearchdescription+xml" title="{{.RepositoryName}}" href="/opensearch.xml" />

	{{if .GeoLocation }}
	{{if .GeoLocation.Coordinates}}
	<meta name="geo.position" content="{{.GeoLocation.Coordinates}}">
	{{end}}

	{{if .GeoLocation.PlaceName}}
	<meta name="geo.placename" content="{{.GeoLocation.PlaceName}}">
	{{end}}
	{{end}}

	<link rel="canonical" href="{{.BaseUrl}}">
	<link rel="alternate" hreflang="{{.LanguageTag}}" href="{{.BaseUrl}}">
	<link rel="alternate" type="application/rss+xml" title="RSS" href="/feed.rss">
	<link rel="shortcut icon" href="/theme/favicon.ico">

	<link rel="stylesheet" href="/theme/screen.css" media="screen">
	<link rel="stylesheet" href="/theme/print.css" media="print">
	<link rel="stylesheet" href="/theme/codehighlighting/highlight.css" media="screen, print">

{{ if .ToplevelNavigation}}

	{{range .ToplevelNavigation.Entries}}

		{{.Title}}

	{{end}}

{{end}}

	<form action="/search" method="GET">
		<input class="typeahead" type="text" name="q" placeholder="search" autocomplete="off">
		<input type="submit" style="visibility:hidden; position: fixed;"/>
	</form>

{{ if .BreadcrumbNavigation}}

	{{range .BreadcrumbNavigation.Entries}}
		{{.Title}}{{if not .IsLast}} » {{end}}
	{{end}}

{{end}}

%s

	{{if .ItemNavigation}}

			{{if .ItemNavigation.Parent}}
			↑ Parent
			{{end}}

			{{if .ItemNavigation.Previous}}
			← Previous
			{{end}}

			{{if .ItemNavigation.Next}}
			Next →
			{{end}}

	{{end}}

	{{ if .Childs }}

Childs

	{{range .Childs}}

		{{.Title}}

{{.Description}}

	{{end}}

	{{end}}

	{{if .TagCloud}}

Tag Cloud

		{{range .TagCloud}}

			{{.Name}}

		{{end}}

	{{end}}

{{if or .PrintUrl .JsonUrl .RtfUrl}}

	{{if .PrintUrl}}
Print
{{end}}
	{{if .JsonUrl}}
JSON
{{end}}
	{{if .RtfUrl}}
Rich Text
{{end}}

{{end}}

Search

Tags

Sitemap

RSS Feed

{{ if .IsRepositoryItem }}

{{ end }}

{{if .Analytics.Enabled}}
{{if .Analytics.GoogleAnalytics.Enabled}}

{{end}}
{{end}}

`, ChildTemplatePlaceholder)
<|endoftext|>


<commit_before>package message

import (
	"errors"
	"fmt"
	"net/http"
	"net/url"
	"socialapi/config"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"
	"time"

	"github.com/koding/bongo"
)

var publicChannel *models.Channel

func Create(u *url.URL, h http.Header, req *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) {

	channelId, err := fetchInitialChannelId(u, c)
	if err != nil {
		return response.NewBadRequest(err)
	}

	// override message type
	// all of the messages coming from client-side
	// should be marked as POST
	req.TypeConstant = models.ChannelMessage_TYPE_POST

	req.InitialChannelId = channelId

	// gets the IP of the Client
	// and adds it to the payload of the ChannelMessage
	cip := string(c.Client.IP)
	req.Payload["ip"] = &cip

	if err := checkThrottle(channelId, req.AccountId); err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.Create(); err != nil {
		// todo this should be internal server error
		return response.NewBadRequest(err)
	}

	cml := models.NewChannelMessageList()
	// override channel id
	cml.ChannelId = channelId
	cml.MessageId = req.Id
	cml.ClientRequestId = req.ClientRequestId
	if err := cml.Create(); err != nil {
		// todo this should be internal server error
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	err = cmc.Fetch(req.Id, request.GetQuery(u))

	// assign client request id back to message response because
	// client uses it for latency compansation
	cmc.Message.ClientRequestId = req.ClientRequestId
	return response.HandleResultAndError(cmc, err)
}

func fetchInitialChannelId(u *url.URL, context *models.Context) (int64, error) {
	channelId, err := request.GetURIInt64(u, "id")
	if err != nil {
		return 0, err
	}

	c, err := models.ChannelById(channelId)
	if err != nil {
		return 0, err
	}

	// when somebody posts on a topic channel, for creating it both in public and topic channels
	// initialChannelId must be set as current group's public channel id
	if c.TypeConstant != models.Channel_TYPE_TOPIC {
		return channelId, nil
	}

	return fetchPublicChannelId(context.GroupName)
}

// TODO when we implement Team product, we will need a better caching mechanism
func fetchPublicChannelId(groupName string) (int64, error) {

	if groupName == "koding" && publicChannel != nil {
		return publicChannel.Id, nil
	}

	channel := models.NewChannel()
	if groupName == "koding" {
		publicChannel = channel
	}

	if err := channel.FetchPublicChannel(groupName); err != nil {
		return 0, err
	}

	return channel.Id, nil
}

func checkThrottle(channelId, requesterId int64) error {
	c, err := models.ChannelById(channelId)
	if err != nil {
		return err
	}

	if c.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	cm := models.NewChannelMessage()

	conf := config.MustGet()

	// if oit is defaul treturn  early
	if conf.Limits.PostThrottleDuration == "" {
		return nil
	}

	// if throttle count is zero, it meands it is not set
	if conf.Limits.PostThrottleCount == 0 {
		return nil
	}

	dur, err := time.ParseDuration(conf.Limits.PostThrottleDuration)
	if err != nil {
		return err
	}

	// subtrack duration from current time
	prevTime := time.Now().UTC().Truncate(dur)

	// count sends positional parameters, no need to sanitize input
	count, err := bongo.B.Count(
		cm,
		"initial_channel_id = ? and "+
			"account_id = ? and "+
			"created_at > ?",
		channelId,
		requesterId,
		prevTime.Format(time.RFC3339Nano),
	)
	if err != nil {
		return err
	}

	if count > conf.Limits.PostThrottleCount {
		return fmt.Errorf("reached to throttle, current post count %d for user %d", count, requesterId)
	}

	return nil
}

func Delete(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	cm := models.NewChannelMessage()
	cm.Id = id

	if err := cm.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	// if this is a reply no need to delete it's replies
	if cm.TypeConstant == models.ChannelMessage_TYPE_REPLY {
		mr := models.NewMessageReply()
		mr.ReplyId = id
		parent, err := mr.FetchParent()
		if err != nil {
			return response.NewBadRequest(err)
		}

		// delete the message here
		err = cm.DeleteMessageAndDependencies(false)
		// then invalidate the cache of the parent message
		bongo.B.AddToCache(parent)

	} else {
		err = cm.DeleteMessageAndDependencies(true)
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	// yes it is deleted but not removed completely from our system
	return response.NewDeleted()
}

func Update(u *url.URL, h http.Header, req *models.ChannelMessage) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	body := req.Body
	payload := req.Payload
	if err := req.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	if req.Id == 0 {
		return response.NewBadRequest(err)
	}

	req.Body = body
	req.Payload = payload
	if err := req.Update(); err != nil {
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	return response.HandleResultAndError(cmc, cmc.Fetch(id, request.GetQuery(u)))
}

func Get(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	cm, err := getMessageByUrl(u)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if cm.Id == 0 {
		return response.NewNotFound()
	}

	cmc := models.NewChannelMessageContainer()
	return response.HandleResultAndError(cmc, cmc.Fetch(cm.Id, request.GetQuery(u)))
}

func getMessageByUrl(u *url.URL) (*models.ChannelMessage, error) {

	// TODO
	// fmt.Println(`
	// 	------->
	//             ADD SECURTY CHECK FOR VISIBILTY OF THE MESSAGE
	//                         FOR THE REQUESTER
	//     ------->"`,
	// )

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return nil, err
	}

	// get url query params
	q := request.GetQuery(u)

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"id": id,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	cm := models.NewChannelMessage()
	// add exempt info
	query.AddScope(models.RemoveTrollContent(cm, q.ShowExempt))

	if err := cm.One(query); err != nil {
		return nil, err
	}

	return cm, nil
}

func GetWithRelated(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	cm, err := getMessageByUrl(u)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if cm.Id == 0 {
		return response.NewNotFound()
	}

	q := request.GetQuery(u)

	cmc := models.NewChannelMessageContainer()
	if err := cmc.Fetch(cm.Id, q); err != nil {
		return response.NewBadRequest(err)
	}

	cmc.AddIsInteracted(q).AddIsFollowed(q)

	return response.HandleResultAndError(cmc, cmc.Err)
}

func GetBySlug(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)

	if q.Slug == "" {
		return response.NewBadRequest(errors.New("slug is not set"))
	}

	cm := models.NewChannelMessage()
	if err := cm.BySlug(q); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	if err := cmc.Fetch(cm.Id, q); err != nil {
		return response.NewBadRequest(err)
	}

	cmc.AddIsInteracted(q).AddIsFollowed(q)

	return response.HandleResultAndError(cmc, cmc.Err)
}
<commit_msg>geoip: controller is written for geoip<commit_after>package message

import (
	"errors"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"socialapi/config"
	"socialapi/models"
	"socialapi/request"
	"socialapi/workers/common/response"
	"socialapi/workers/helper"
	"time"

	"github.com/jinzhu/gorm"
	"github.com/koding/bongo"
)

var publicChannel *models.Channel

func Create(u *url.URL, h http.Header, req *models.ChannelMessage, c *models.Context) (int, http.Header, interface{}, error) {

	channelId, err := fetchInitialChannelId(u, c)
	if err != nil {
		return response.NewBadRequest(err)
	}

	// override message type
	// all of the messages coming from client-side
	// should be marked as POST
	req.TypeConstant = models.ChannelMessage_TYPE_POST

	req.InitialChannelId = channelId

	if req.Payload == nil {
		req.Payload = gorm.Hstore{}
	}

	if _, ok := req.Payload["saveLocation"]; ok {
		// gets the IP of the Client
		// and adds it to the payload of the ChannelMessage
		record, err := helper.MustGetGeoIPDB().City(c.Client.IP)
		if err != nil {
			log.Fatal(err)
		}

		ll := record.City.Names["en"]

		req.Payload["location"] = &ll
	}

	if err := checkThrottle(channelId, req.AccountId); err != nil {
		return response.NewBadRequest(err)
	}

	if err := req.Create(); err != nil {
		// todo this should be internal server error
		return response.NewBadRequest(err)
	}

	cml := models.NewChannelMessageList()
	// override channel id
	cml.ChannelId = channelId
	cml.MessageId = req.Id
	cml.ClientRequestId = req.ClientRequestId
	if err := cml.Create(); err != nil {
		// todo this should be internal server error
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	err = cmc.Fetch(req.Id, request.GetQuery(u))

	// assign client request id back to message response because
	// client uses it for latency compansation
	cmc.Message.ClientRequestId = req.ClientRequestId
	return response.HandleResultAndError(cmc, err)
}

func fetchInitialChannelId(u *url.URL, context *models.Context) (int64, error) {
	channelId, err := request.GetURIInt64(u, "id")
	if err != nil {
		return 0, err
	}

	c, err := models.ChannelById(channelId)
	if err != nil {
		return 0, err
	}

	// when somebody posts on a topic channel, for creating it both in public and topic channels
	// initialChannelId must be set as current group's public channel id
	if c.TypeConstant != models.Channel_TYPE_TOPIC {
		return channelId, nil
	}

	return fetchPublicChannelId(context.GroupName)
}

// TODO when we implement Team product, we will need a better caching mechanism
func fetchPublicChannelId(groupName string) (int64, error) {

	if groupName == "koding" && publicChannel != nil {
		return publicChannel.Id, nil
	}

	channel := models.NewChannel()
	if groupName == "koding" {
		publicChannel = channel
	}

	if err := channel.FetchPublicChannel(groupName); err != nil {
		return 0, err
	}

	return channel.Id, nil
}

func checkThrottle(channelId, requesterId int64) error {
	c, err := models.ChannelById(channelId)
	if err != nil {
		return err
	}

	if c.TypeConstant != models.Channel_TYPE_GROUP {
		return nil
	}

	cm := models.NewChannelMessage()

	conf := config.MustGet()

	// if oit is defaul treturn  early
	if conf.Limits.PostThrottleDuration == "" {
		return nil
	}

	// if throttle count is zero, it meands it is not set
	if conf.Limits.PostThrottleCount == 0 {
		return nil
	}

	dur, err := time.ParseDuration(conf.Limits.PostThrottleDuration)
	if err != nil {
		return err
	}

	// subtrack duration from current time
	prevTime := time.Now().UTC().Truncate(dur)

	// count sends positional parameters, no need to sanitize input
	count, err := bongo.B.Count(
		cm,
		"initial_channel_id = ? and "+
			"account_id = ? and "+
			"created_at > ?",
		channelId,
		requesterId,
		prevTime.Format(time.RFC3339Nano),
	)
	if err != nil {
		return err
	}

	if count > conf.Limits.PostThrottleCount {
		return fmt.Errorf("reached to throttle, current post count %d for user %d", count, requesterId)
	}

	return nil
}

func Delete(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	cm := models.NewChannelMessage()
	cm.Id = id

	if err := cm.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	// if this is a reply no need to delete it's replies
	if cm.TypeConstant == models.ChannelMessage_TYPE_REPLY {
		mr := models.NewMessageReply()
		mr.ReplyId = id
		parent, err := mr.FetchParent()
		if err != nil {
			return response.NewBadRequest(err)
		}

		// delete the message here
		err = cm.DeleteMessageAndDependencies(false)
		// then invalidate the cache of the parent message
		bongo.B.AddToCache(parent)

	} else {
		err = cm.DeleteMessageAndDependencies(true)
	}

	if err != nil {
		return response.NewBadRequest(err)
	}

	// yes it is deleted but not removed completely from our system
	return response.NewDeleted()
}

func Update(u *url.URL, h http.Header, req *models.ChannelMessage) (int, http.Header, interface{}, error) {
	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return response.NewBadRequest(err)
	}

	body := req.Body
	payload := req.Payload
	if err := req.ById(id); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	if req.Id == 0 {
		return response.NewBadRequest(err)
	}

	req.Body = body
	req.Payload = payload
	if err := req.Update(); err != nil {
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	return response.HandleResultAndError(cmc, cmc.Fetch(id, request.GetQuery(u)))
}

func Get(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	cm, err := getMessageByUrl(u)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if cm.Id == 0 {
		return response.NewNotFound()
	}

	cmc := models.NewChannelMessageContainer()
	return response.HandleResultAndError(cmc, cmc.Fetch(cm.Id, request.GetQuery(u)))
}

func getMessageByUrl(u *url.URL) (*models.ChannelMessage, error) {

	// TODO
	// fmt.Println(`
	// 	------->
	//             ADD SECURTY CHECK FOR VISIBILTY OF THE MESSAGE
	//                         FOR THE REQUESTER
	//     ------->"`,
	// )

	id, err := request.GetURIInt64(u, "id")
	if err != nil {
		return nil, err
	}

	// get url query params
	q := request.GetQuery(u)

	query := &bongo.Query{
		Selector: map[string]interface{}{
			"id": id,
		},
		Pagination: *bongo.NewPagination(1, 0),
	}

	cm := models.NewChannelMessage()
	// add exempt info
	query.AddScope(models.RemoveTrollContent(cm, q.ShowExempt))

	if err := cm.One(query); err != nil {
		return nil, err
	}

	return cm, nil
}

func GetWithRelated(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	cm, err := getMessageByUrl(u)
	if err != nil {
		return response.NewBadRequest(err)
	}

	if cm.Id == 0 {
		return response.NewNotFound()
	}

	q := request.GetQuery(u)

	cmc := models.NewChannelMessageContainer()
	if err := cmc.Fetch(cm.Id, q); err != nil {
		return response.NewBadRequest(err)
	}

	cmc.AddIsInteracted(q).AddIsFollowed(q)

	return response.HandleResultAndError(cmc, cmc.Err)
}

func GetBySlug(u *url.URL, h http.Header, _ interface{}) (int, http.Header, interface{}, error) {
	q := request.GetQuery(u)

	if q.Slug == "" {
		return response.NewBadRequest(errors.New("slug is not set"))
	}

	cm := models.NewChannelMessage()
	if err := cm.BySlug(q); err != nil {
		if err == bongo.RecordNotFound {
			return response.NewNotFound()
		}
		return response.NewBadRequest(err)
	}

	cmc := models.NewChannelMessageContainer()
	if err := cmc.Fetch(cm.Id, q); err != nil {
		return response.NewBadRequest(err)
	}

	cmc.AddIsInteracted(q).AddIsFollowed(q)

	return response.HandleResultAndError(cmc, cmc.Err)
}
<|endoftext|>


<commit_before>package services

import (
	"os"
	"fmt"
	"net/http"
	"encoding/json"
	"github.com/jmoiron/jsonq"
)

const (
	slackUserListURL = "https://slack.com/api/users.list"
)

func SlackUserList() ([]interface{}){
	if token := os.Getenv("SLACK_API_TOKEN"); token == "" {
		return nil, fmt.Errorf("You need to pass SLACK_API_TOKEN as environment variable")
	}
	requestURL := slackUserListURL + "?token=" + token
	resp, err := http.Get(requestURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	data := map[string]interface{}{}
	dec := json.NewDecoder(resp.Body)
	dec.Decode(&data)
	jq := jsonq.NewQuery(data)
	arr, err := jq.Array("members")
	return arr, err
}
<commit_msg>Map inside slack service<commit_after>package services

import (
	"os"
	"fmt"
	"net/http"
	"encoding/json"
	"github.com/jmoiron/jsonq"
	"strconv"
)

const (
	slackUserListURL = "https://slack.com/api/users.list"
)

func SlackUserList() (map[string]string, error){
	token := os.Getenv("SLACK_API_TOKEN")
	if token == "" {
		return nil, fmt.Errorf("You need to pass SLACK_API_TOKEN as environment variable")
	}
	requestURL := slackUserListURL + "?token=" + token
	resp, err := http.Get(requestURL)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	data := map[string]interface{}{}
	dec := json.NewDecoder(resp.Body)
	dec.Decode(&data)
	jq := jsonq.NewQuery(data)
	arr, err := jq.Array("members")

	users := make(map[string]string)
	for i := 0; i < len(arr); i++ {
		id, _ := jq.String("members", strconv.Itoa(i), "id")
		name, _ := jq.String("members", strconv.Itoa(i), "name")
		users[name] = id
	}
	return users, err
}
<|endoftext|>


<commit_before>package tuikit

import "time"

type ProgressSpinner struct {
	*TextView

	spinRunes []rune
	current   int
}

func NewProgressSpinner() *ProgressSpinner {
	ps := &ProgressSpinner{
		TextView:  NewTextView(),
		spinRunes: []rune{'|', '/', '—', '\\', '|', '/', '—', '\\'},
	}

	go func() {
		l := len(ps.spinRunes)
		for _ = range time.Tick(150 * time.Millisecond) {
			ps.current = (ps.current + 1) % l
			ps.SetText(string(ps.spinRunes[ps.current]))
		}
	}()

	return ps
}
<commit_msg>Adjust ProgressSpinner tick time to 110 ms<commit_after>package tuikit

import "time"

type ProgressSpinner struct {
	*TextView

	spinRunes []rune
	current   int
}

func NewProgressSpinner() *ProgressSpinner {
	ps := &ProgressSpinner{
		TextView:  NewTextView(),
		spinRunes: []rune{'|', '/', '—', '\\', '|', '/', '—', '\\'},
	}

	go func() {
		l := len(ps.spinRunes)
		for _ = range time.Tick(110 * time.Millisecond) {
			ps.current = (ps.current + 1) % l
			ps.SetText(string(ps.spinRunes[ps.current]))
		}
	}()

	return ps
}
<|endoftext|>


<commit_before>package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/julienschmidt/httprouter"
)

func Test_helloHandler(t *testing.T) {
	router := httprouter.New()
	router.GET("/hello", helloHandler)
	// router.Handle("GET", "/hello", helloHandler)

	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/hello", nil)
	if err != nil {
		t.Fatal(err)
	}

	router.ServeHTTP(w, r)
	if w.Code != http.StatusOK {
		t.Errorf("Wrong status: wanted %v, but got %v", http.StatusOK, w.Code)
	}
}
<commit_msg>cleanup<commit_after>package main

import (
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/julienschmidt/httprouter"
)

func Test_helloHandler(t *testing.T) {
	router := httprouter.New()
	router.GET("/hello", helloHandler)
	// router.Handle("GET", "/hello", helloHandler)

	w := httptest.NewRecorder()
	r, err := http.NewRequest("GET", "/hello", nil)
	if err != nil {
		t.Fatal(err)
	}

	router.ServeHTTP(w, r)
	if w.Code != http.StatusOK {
		t.Errorf("Wrong status: wanted %v, but got %v", http.StatusOK, w.Code)
	}
}

// references:
// see this blog for more complex examples: https://medium.com/@gauravsingharoy/build-your-first-api-server-with-httprouter-in-golang-732b7b01f6ab<|endoftext|>


<commit_before>package endpointanalysisdiagram

import (
	"fmt"
	"strings"

	"github.com/anz-bank/sysl/pkg/sysl"
)

const projectDir = "../../../"

//Keeps track of the statement-endpoint pairs we visit during execution
type externalLink struct {
	statement, endPoint string
}

//Accepts the sysl module and returns a string (and an error if any)
//The resulting string is the mermaid code for the endpoint analysis for that application and endpoint
func GenerateEndpointAnalysisDiagram(m *sysl.Module) (string, error) {
	return generateEndpointAnalysisDiagram(m, &[]externalLink{}, true)
}

//This is a helper which has additional arguments which need not be entered by the user
func generateEndpointAnalysisDiagram(m *sysl.Module, externalLinks *[]externalLink, theStart bool) (string, error) {
	var result string
	if theStart {
		result = "%% AUTOGENERATED CODE -- DO NOT EDIT!\n\ngraph TD\n"
	}
	for appName, app := range m.Apps {
		result += fmt.Sprintf(" subgraph %s\n", appName)
		for epName, endPoint := range app.Endpoints {
			statements := endPoint.Stmt
			result += printEndpointAnalysisStatements(m, statements, cleanString(epName), externalLinks)
		}
		result += fmt.Sprintf(" end\n")
	}
	for _, eLink := range *externalLinks {
		result += fmt.Sprintf(" %s-->%s\n", eLink.statement, eLink.endPoint)
	}
	return result, nil
}

//This function is used to print the mermaid code for different sysl statements
func printEndpointAnalysisStatements(m *sysl.Module, statements []*sysl.Statement,
	endPoint string, externalLinks *[]externalLink) string {
	var result string
	for _, statement := range statements {
		switch c := statement.Stmt.(type) {
		case *sysl.Statement_Call:
			appEndPoint := fmt.Sprintf("%s-%s", cleanString(c.Call.Target.Part[0]), cleanString(c.Call.Endpoint))
			result += fmt.Sprintf(" %s-->%s\n", endPoint, appEndPoint)
			pair := externalLink{appEndPoint, cleanString(c.Call.Endpoint)}
			if !externalLinksContain(*externalLinks, pair) {
				*externalLinks = append(*externalLinks, pair)
			}
		case *sysl.Statement_Group:
			result += printEndpointAnalysisStatements(m, c.Group.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Cond:
			result += printEndpointAnalysisStatements(m, c.Cond.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Loop:
			result += printEndpointAnalysisStatements(m, c.Loop.Stmt, endPoint, externalLinks)
		case *sysl.Statement_LoopN:
			result += printEndpointAnalysisStatements(m, c.LoopN.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Foreach:
			result += printEndpointAnalysisStatements(m, c.Foreach.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Action:
			result += fmt.Sprintf(" %s-->%s\n", endPoint, cleanString(c.Action.Action))
		case *sysl.Statement_Ret:
			result += fmt.Sprintf(" %s-->%s\n", endPoint, cleanString(c.Ret.Payload))
		default:
			panic("Unrecognised statement type")
		}
	}
	return result
}

//Checks if the statement-endpoint group have been already visited or not
func externalLinksContain(i []externalLink, ip externalLink) bool {
	for _, a := range i {
		if a == ip {
			return true
		}
	}
	return false
}

//Replaces certain characters in the string suitable for mermaid
//TODO:Replace more characters if necessary
func cleanString(temp string) string {
	temp = strings.ReplaceAll(temp, " ", "")
	temp = strings.ReplaceAll(temp, "{", "_")
	temp = strings.ReplaceAll(temp, "}", "_")
	temp = strings.ReplaceAll(temp, "[", "_")
	temp = strings.ReplaceAll(temp, "]", "_")
	temp = strings.ReplaceAll(temp, "\"", "")
	temp = strings.ReplaceAll(temp, "~", "")
	return temp
}
<commit_msg>Fix local-only linter complaint (#815)<commit_after>package endpointanalysisdiagram

import (
	"fmt"
	"strings"

	"github.com/anz-bank/sysl/pkg/sysl"
)

const projectDir = "../../../"

//Keeps track of the statement-endpoint pairs we visit during execution
type externalLink struct {
	statement, endPoint string
}

//Accepts the sysl module and returns a string (and an error if any)
//The resulting string is the mermaid code for the endpoint analysis for that application and endpoint
func GenerateEndpointAnalysisDiagram(m *sysl.Module) (string, error) {
	return generateEndpointAnalysisDiagram(m, &[]externalLink{}, true)
}

//This is a helper which has additional arguments which need not be entered by the user
func generateEndpointAnalysisDiagram(m *sysl.Module, externalLinks *[]externalLink, theStart bool) (string, error) {
	var result string
	if theStart {
		result = "%% AUTOGENERATED CODE -- DO NOT EDIT!\n\ngraph TD\n"
	}
	for appName, app := range m.Apps {
		result += fmt.Sprintf(" subgraph %s\n", appName)
		for epName, endPoint := range app.Endpoints {
			statements := endPoint.Stmt
			result += printEndpointAnalysisStatements(m, statements, cleanString(epName), externalLinks)
		}
		result += " end\n"
	}
	for _, eLink := range *externalLinks {
		result += fmt.Sprintf(" %s-->%s\n", eLink.statement, eLink.endPoint)
	}
	return result, nil
}

//This function is used to print the mermaid code for different sysl statements
func printEndpointAnalysisStatements(m *sysl.Module, statements []*sysl.Statement,
	endPoint string, externalLinks *[]externalLink) string {
	var result string
	for _, statement := range statements {
		switch c := statement.Stmt.(type) {
		case *sysl.Statement_Call:
			appEndPoint := fmt.Sprintf("%s-%s", cleanString(c.Call.Target.Part[0]), cleanString(c.Call.Endpoint))
			result += fmt.Sprintf(" %s-->%s\n", endPoint, appEndPoint)
			pair := externalLink{appEndPoint, cleanString(c.Call.Endpoint)}
			if !externalLinksContain(*externalLinks, pair) {
				*externalLinks = append(*externalLinks, pair)
			}
		case *sysl.Statement_Group:
			result += printEndpointAnalysisStatements(m, c.Group.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Cond:
			result += printEndpointAnalysisStatements(m, c.Cond.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Loop:
			result += printEndpointAnalysisStatements(m, c.Loop.Stmt, endPoint, externalLinks)
		case *sysl.Statement_LoopN:
			result += printEndpointAnalysisStatements(m, c.LoopN.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Foreach:
			result += printEndpointAnalysisStatements(m, c.Foreach.Stmt, endPoint, externalLinks)
		case *sysl.Statement_Action:
			result += fmt.Sprintf(" %s-->%s\n", endPoint, cleanString(c.Action.Action))
		case *sysl.Statement_Ret:
			result += fmt.Sprintf(" %s-->%s\n", endPoint, cleanString(c.Ret.Payload))
		default:
			panic("Unrecognised statement type")
		}
	}
	return result
}

//Checks if the statement-endpoint group have been already visited or not
func externalLinksContain(i []externalLink, ip externalLink) bool {
	for _, a := range i {
		if a == ip {
			return true
		}
	}
	return false
}

//Replaces certain characters in the string suitable for mermaid
//TODO:Replace more characters if necessary
func cleanString(temp string) string {
	temp = strings.ReplaceAll(temp, " ", "")
	temp = strings.ReplaceAll(temp, "{", "_")
	temp = strings.ReplaceAll(temp, "}", "_")
	temp = strings.ReplaceAll(temp, "[", "_")
	temp = strings.ReplaceAll(temp, "]", "_")
	temp = strings.ReplaceAll(temp, "\"", "")
	temp = strings.ReplaceAll(temp, "~", "")
	return temp
}
<|endoftext|>


<commit_before>package start

import (
	"fmt"
	"bytes"

	"github.com/MarcosSegovia/sammy-the-bot/sammy"
	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type Start struct {
	sammy *sammy.Sammy
	cmd   *sammy.Cmd
}

func NewStart(sam *sammy.Sammy) *Start {
	s := new(Start)
	s.sammy = sam
	s.cmd = sammy.NewCommand("start", "/start", "Initialize Sammy :D")
	return s
}

func (s *Start) Evaluate(msg *tgbotapi.Message) (bool, error) {
	if msg.Text != s.cmd.Exec {
		return false, nil
	}
	userId, err := s.sammy.GetUserIdByChatId(msg.Chat.ID)
	if err != nil {
		return false, fmt.Errorf("could not add user because: %v", err)
	}
	if userId == "" {
		err = s.sammy.AddUser(sammy.NewUser(msg.Chat.ID, msg.Chat.UserName))
	}

	var buffer bytes.Buffer
	buffer.WriteString("Hi there ! "+ userId +"\n")
	buffer.WriteString("Im your botpher assistance on whatever you need.\n My source code is in https://github.com/MarcosSegovia/sammy-the-bot\n Just follow /help to see things I can do. \n\n")
	newMsg := tgbotapi.NewMessage(msg.Chat.ID, buffer.String())
	_, err = s.sammy.Api.Send(newMsg)
	if err != nil {
		return false, fmt.Errorf("could not send message because: %v", err)
	}
	return true, nil
}

func (s *Start) Description() string {
	return s.cmd.Exec + " - " + s.cmd.Desc
}
<commit_msg>Deleting userId from welcome message<commit_after>package start

import (
	"fmt"
	"bytes"

	"github.com/MarcosSegovia/sammy-the-bot/sammy"
	"github.com/go-telegram-bot-api/telegram-bot-api"
)

type Start struct {
	sammy *sammy.Sammy
	cmd   *sammy.Cmd
}

func NewStart(sam *sammy.Sammy) *Start {
	s := new(Start)
	s.sammy = sam
	s.cmd = sammy.NewCommand("start", "/start", "Initialize Sammy :D")
	return s
}

func (s *Start) Evaluate(msg *tgbotapi.Message) (bool, error) {
	if msg.Text != s.cmd.Exec {
		return false, nil
	}
	userId, err := s.sammy.GetUserIdByChatId(msg.Chat.ID)
	if err != nil {
		return false, fmt.Errorf("could not add user because: %v", err)
	}
	if userId == "" {
		err = s.sammy.AddUser(sammy.NewUser(msg.Chat.ID, msg.Chat.UserName))
	}

	var buffer bytes.Buffer
	buffer.WriteString("Hi there !\n")
	buffer.WriteString("Im your botpher assistance on whatever you need.\n My source code is in https://github.com/MarcosSegovia/sammy-the-bot\n Just follow /help to see things I can do. \n\n")
	newMsg := tgbotapi.NewMessage(msg.Chat.ID, buffer.String())
	_, err = s.sammy.Api.Send(newMsg)
	if err != nil {
		return false, fmt.Errorf("could not send message because: %v", err)
	}
	return true, nil
}

func (s *Start) Description() string {
	return s.cmd.Exec + " - " + s.cmd.Desc
}
<|endoftext|>


<commit_before>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux darwin dragonfly freebsd openbsd netbsd solaris

package tar

import (
	"io"
	"os"
	"syscall"
)

func init() {
	sysSparseDetect = sparseDetectUnix
}

func sparseDetectUnix(f *os.File) (sph sparseHoles, err error) {
	// SEEK_DATA and SEEK_HOLE originated from Solaris and support for it
	// has been added to most of the other major Unix systems.
	const seekData = 3 // SEEK_DATA from unistd.h
	const seekHole = 4 // SEEK_HOLE from unistd.h

	// Check for seekData/seekHole support.
	if _, err := f.Seek(0, seekHole); errno(err) == syscall.EINVAL {
		return nil, nil // Either old kernel or FS does not support this
	}

	// Populate the SparseHoles.
	var last, pos int64 = -1, 0
	for {
		// Get the location of the next hole section.
		if pos, err = fseek(f, pos, seekHole); pos == last || err != nil {
			return sph, err
		}
		offset := pos
		last = pos

		// Get the location of the next data section.
		if pos, err = fseek(f, pos, seekData); pos == last || err != nil {
			return sph, err
		}
		length := pos - offset
		last = pos

		if length > 0 {
			sph = append(sph, SparseEntry{offset, length})
		}
	}
}

func fseek(f *os.File, pos int64, whence int) (int64, error) {
	pos, err := f.Seek(pos, whence)
	if errno(err) == syscall.ENXIO {
		// SEEK_DATA returns ENXIO when past the last data fragment,
		// which makes determining the size of the last hole difficult.
		pos, err = f.Seek(0, io.SeekEnd)
	}
	return pos, err
}

func errno(err error) error {
	if perr, ok := err.(*os.PathError); ok {
		return perr.Err
	}
	return err
}
<commit_msg>archive/tar: make check for hole detection support more liberal<commit_after>// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// +build linux darwin dragonfly freebsd openbsd netbsd solaris

package tar

import (
	"io"
	"os"
	"syscall"
)

func init() {
	sysSparseDetect = sparseDetectUnix
}

func sparseDetectUnix(f *os.File) (sph sparseHoles, err error) {
	// SEEK_DATA and SEEK_HOLE originated from Solaris and support for it
	// has been added to most of the other major Unix systems.
	const seekData = 3 // SEEK_DATA from unistd.h
	const seekHole = 4 // SEEK_HOLE from unistd.h

	// Check for seekData/seekHole support.
	// Different OS and FS may differ in the exact errno that is returned when
	// there is no support. Rather than special-casing every possible errno
	// representing "not supported", just assume that a non-nil error means
	// that seekData/seekHole is not supported.
	if _, err := f.Seek(0, seekHole); err != nil {
		return nil, nil
	}

	// Populate the SparseHoles.
	var last, pos int64 = -1, 0
	for {
		// Get the location of the next hole section.
		if pos, err = fseek(f, pos, seekHole); pos == last || err != nil {
			return sph, err
		}
		offset := pos
		last = pos

		// Get the location of the next data section.
		if pos, err = fseek(f, pos, seekData); pos == last || err != nil {
			return sph, err
		}
		length := pos - offset
		last = pos

		if length > 0 {
			sph = append(sph, SparseEntry{offset, length})
		}
	}
}

func fseek(f *os.File, pos int64, whence int) (int64, error) {
	pos, err := f.Seek(pos, whence)
	if errno(err) == syscall.ENXIO {
		// SEEK_DATA returns ENXIO when past the last data fragment,
		// which makes determining the size of the last hole difficult.
		pos, err = f.Seek(0, io.SeekEnd)
	}
	return pos, err
}

func errno(err error) error {
	if perr, ok := err.(*os.PathError); ok {
		return perr.Err
	}
	return err
}
<|endoftext|>