<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestVerifyRunningTask(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-apps-response.json")
	assert.Nil(t, err)

	ok, err := verifyRunningTask(appID, appVersion, taskID, response)
	assert.True(t, ok)

	// Verify that appID is checked
	ok, err = verifyRunningTask("/demo/webap1", appVersion, taskID, response)
	assert.False(t, ok)

	// Verify that appVersion is checked
	ok, err = verifyRunningTask(appID, "2014-12-04T12:25:08.426Z", taskID, response)
	assert.False(t, ok)

	// Verify that taskID is checked
	ok, err = verifyRunningTask(appID, appVersion, "demo_webap1.0f810e10-9a82-11e5-94c7-6a515f434e2d", response)
	assert.False(t, ok)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`{}`))
	assert.False(t, ok)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`{"app": {}}`))
	assert.False(t, ok)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`%"#¤%"#¤`))
	assert.False(t, ok)
}

func TestParseApplicationVersion(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-response.json")
	assert.Nil(t, err)

	app, err := parseApplicationVersion(appID, appVersion, taskID, response)
	assert.Nil(t, err)
	assert.Equal(t, appID, app.ID)
	assert.Equal(t, appVersion, app.Version)
	assert.Equal(t, taskID, app.TaskID)
	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Equal(t, "kVOhhw2wAJuAofxO7h4EM0xboxGAwnsq9J6fluFY5CQ=", encode(app.ServiceKey[:]))

	// Verify that appID is checked
	app, err = parseApplicationVersion("/demo/webap1", "2015-12-04T12:25:08.426Z", taskID, response)
	assert.Nil(t, app)
	assert.NotNil(t, err)

	// Verify that appVersion is checked
	app, err = parseApplicationVersion(appID, "2014-12-04T12:25:08.426Z", taskID, response)
	assert.Nil(t, app)
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`{}`))
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`{"id": "/demo/webapp"}`))
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`%"#¤%"#¤`))
	assert.NotNil(t, err)
}

func TestParseApplicationWithoutServiceKey(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp2", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-nosvckey.json")
	assert.Nil(t, err)

	app, err := parseApplicationVersion(appID, appVersion, taskID, response)
	assert.Nil(t, err)
	assert.Equal(t, appID, app.ID)
	assert.Equal(t, appVersion, app.Version)
	assert.Equal(t, taskID, app.TaskID)

	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Nil(t, app.ServiceKey)
}

func TestParseApplicationWithoutDeployKey(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-nodepkey.json")
	assert.Nil(t, err)

	_, err = parseApplicationVersion(appID, appVersion, taskID, response)
	assert.NotNil(t, err)
	assert.Equal(t, "App is missing $DEPLOY_PUBLIC_KEY in the Marathon config \"env\" section", err.Error())
}

func TestGetMarathonApp(t *testing.T) {
	appsResponse, err := ioutil.ReadFile("./resources/test/marathon-apps-response.json")
	assert.Nil(t, err)

	versionsResponse, err := ioutil.ReadFile("./resources/test/marathon-versions-response.json")
	assert.Nil(t, err)

	// Start in-test HTTP server that emulates Marathon
	marathon := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		switch {
		case r.URL.Path == "/v2/apps/demo/webapp" && r.URL.RawQuery == "embed=apps.tasks":
			fmt.Fprintln(w, string(appsResponse))
		case r.URL.Path == "/v2/apps/demo/webapp/versions/2015-12-04T12:25:08.426Z":
			fmt.Fprintln(w, string(versionsResponse))
		default:
			http.Error(w, fmt.Sprintf("Bad URL %s", r.URL.Path), http.StatusNotFound)
		}
	}))
	defer marathon.Close()

	app, err := getMarathonApp(marathon.URL, "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d")
	assert.Nil(t, err)
	assert.Equal(t, "/demo/webapp", app.ID)
	assert.Equal(t, "2015-12-04T12:25:08.426Z", app.Version)
	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Equal(t, "kVOhhw2wAJuAofxO7h4EM0xboxGAwnsq9J6fluFY5CQ=", encode(app.ServiceKey[:]))
	assert.Equal(t, "ENC[NACL,", app.Env["DATABASE_PASSWORD"][0:9])
}
<commit_msg>Check error return value in test<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestVerifyRunningTask(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-apps-response.json")
	assert.Nil(t, err)

	ok, err := verifyRunningTask(appID, appVersion, taskID, response)
	assert.True(t, ok)
	assert.Nil(t, err)

	// Verify that appID is checked
	ok, err = verifyRunningTask("/demo/webap1", appVersion, taskID, response)
	assert.False(t, ok)
	assert.NotNil(t, err)

	// Verify that appVersion is checked
	ok, err = verifyRunningTask(appID, "2014-12-04T12:25:08.426Z", taskID, response)
	assert.False(t, ok)
	assert.NotNil(t, err)

	// Verify that taskID is checked
	ok, err = verifyRunningTask(appID, appVersion, "demo_webap1.0f810e10-9a82-11e5-94c7-6a515f434e2d", response)
	assert.False(t, ok)
	assert.NotNil(t, err)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`{}`))
	assert.False(t, ok)
	assert.NotNil(t, err)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`{"app": {}}`))
	assert.False(t, ok)
	assert.NotNil(t, err)

	// Verify bad responses
	ok, err = verifyRunningTask(appID, appVersion, taskID, []byte(`%"#¤%"#¤`))
	assert.False(t, ok)
	assert.NotNil(t, err)
}

func TestParseApplicationVersion(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-response.json")
	assert.Nil(t, err)

	app, err := parseApplicationVersion(appID, appVersion, taskID, response)
	assert.Nil(t, err)
	assert.Equal(t, appID, app.ID)
	assert.Equal(t, appVersion, app.Version)
	assert.Equal(t, taskID, app.TaskID)
	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Equal(t, "kVOhhw2wAJuAofxO7h4EM0xboxGAwnsq9J6fluFY5CQ=", encode(app.ServiceKey[:]))

	// Verify that appID is checked
	app, err = parseApplicationVersion("/demo/webap1", "2015-12-04T12:25:08.426Z", taskID, response)
	assert.Nil(t, app)
	assert.NotNil(t, err)

	// Verify that appVersion is checked
	app, err = parseApplicationVersion(appID, "2014-12-04T12:25:08.426Z", taskID, response)
	assert.Nil(t, app)
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`{}`))
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`{"id": "/demo/webapp"}`))
	assert.NotNil(t, err)

	// Verify bad responses
	app, err = parseApplicationVersion(appID, appVersion, taskID, []byte(`%"#¤%"#¤`))
	assert.NotNil(t, err)
}

func TestParseApplicationWithoutServiceKey(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp2", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-nosvckey.json")
	assert.Nil(t, err)

	app, err := parseApplicationVersion(appID, appVersion, taskID, response)
	assert.Nil(t, err)
	assert.Equal(t, appID, app.ID)
	assert.Equal(t, appVersion, app.Version)
	assert.Equal(t, taskID, app.TaskID)

	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Nil(t, app.ServiceKey)
}

func TestParseApplicationWithoutDeployKey(t *testing.T) {
	appID, appVersion, taskID := "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d"

	response, err := ioutil.ReadFile("./resources/test/marathon-versions-nodepkey.json")
	assert.Nil(t, err)

	_, err = parseApplicationVersion(appID, appVersion, taskID, response)
	assert.NotNil(t, err)
	assert.Equal(t, "App is missing $DEPLOY_PUBLIC_KEY in the Marathon config \"env\" section", err.Error())
}

func TestGetMarathonApp(t *testing.T) {
	appsResponse, err := ioutil.ReadFile("./resources/test/marathon-apps-response.json")
	assert.Nil(t, err)

	versionsResponse, err := ioutil.ReadFile("./resources/test/marathon-versions-response.json")
	assert.Nil(t, err)

	// Start in-test HTTP server that emulates Marathon
	marathon := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		switch {
		case r.URL.Path == "/v2/apps/demo/webapp" && r.URL.RawQuery == "embed=apps.tasks":
			fmt.Fprintln(w, string(appsResponse))
		case r.URL.Path == "/v2/apps/demo/webapp/versions/2015-12-04T12:25:08.426Z":
			fmt.Fprintln(w, string(versionsResponse))
		default:
			http.Error(w, fmt.Sprintf("Bad URL %s", r.URL.Path), http.StatusNotFound)
		}
	}))
	defer marathon.Close()

	app, err := getMarathonApp(marathon.URL, "/demo/webapp", "2015-12-04T12:25:08.426Z", "demo_webapp.0f810e10-9a82-11e5-94c7-6a515f434e2d")
	assert.Nil(t, err)
	assert.Equal(t, "/demo/webapp", app.ID)
	assert.Equal(t, "2015-12-04T12:25:08.426Z", app.Version)
	assert.Equal(t, "omO6DSEw/mZDG9NuhyEC4uYbgwwqEivOuX0EqX9+Ql0=", encode(app.DeployKey[:]))
	assert.Equal(t, "kVOhhw2wAJuAofxO7h4EM0xboxGAwnsq9J6fluFY5CQ=", encode(app.ServiceKey[:]))
	assert.Equal(t, "ENC[NACL,", app.Env["DATABASE_PASSWORD"][0:9])
}
<|endoftext|>


<commit_before>package main

import (
	"bufio"
	"compress/gzip"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

type Domain struct {
	Name     string
	Reg      string
	Create   string
	PaidTill string
	FreeDate string
	TLSVer   string
}

func main() {
	var zones [1]string
	var err error
	zones[0] = "ru"

	zoneFile := fmt.Sprintf("%s_zone.gz", zones[0])
	zoneFileDecompressed := "zone_ru"

	err := DownloadFile(zoneFile, zoneUrl)
	if err != nil {
		log.Fatal(err)
	}
	err = DecompressFile(zoneFile, zoneFileDecompressed)
	if err != nil {
		log.Fatal(err)
	}

	Domains := LoadData(zoneFileDecompressed)
	err = CheckTLSVersion(Domains)
}

func DownloadFile(filepath string, url string) error {
	resp, err := http.Get(url)
	buf := make([]byte, 1024)
	bytesRead := 0

	if err != nil {
		return err
	}

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	for {
		n, err := resp.Body.Read(buf)
		if err != nil {
			if err == io.EOF {
				_, err = out.Write(buf[:n])
				if err != nil {
					log.Fatal(err)
				}
				break
			}
			log.Fatal(err)
		}
		_, err = out.Write(buf[:n])
		if err != nil {
			log.Fatal(err)
		}
		bytesRead += n
	}
	defer resp.Body.Close()
	return err
}

func DecompressFile(gzipped string, ungzipped string) error {
	buf := make([]byte, 1024)
	input, err := os.Open(gzipped)
	if err != nil {
		log.Fatal(err)
	}
	r, err := gzip.NewReader(input)
	if err != nil {
		log.Fatal(err)
	}
	out, _ := os.Create(ungzipped)
	for {
		n, err := r.Read(buf)
		if err != nil {
			if err == io.EOF {
				_, err = out.Write(buf[:n])
				if err != nil {
					log.Fatal(err)
				}
				break
			}
			log.Fatal(err)
		}

		fmt.Println(n)
		_, err = out.Write(buf[:n])
		if err != nil {
			log.Fatal(err)
		}

	}
	return err
}

func LoadData(dataFilePath string) []Domain {
	var Domains []Domain
	fd, err := os.Open(dataFilePath)
	if err != nil {
		log.Fatal(err)
	}

	s := bufio.NewScanner(fd)
	s.Split(bufio.ScanLines)
	for s.Scan() {
		line := strings.Fields(s.Text())
		Domains = append(Domains, Domain{line[0], line[1], line[2], line[3], line[4], ""})
	}
	return Domains
}

func CheckTLSVersion(Domains []Domain) error {
	var err error
	var wg sync.WaitGroup
	for i := 1; i < len(Domains); i++ {
		wg.Add(1)
		go SendRequest(Domains[i])
	}
	wg.Wait()
	return err
}

func SendRequest(domain Domain) error {
	url := fmt.Sprintf("https://%s", domain.Name)
	resp, err := http.Get(url)
	if err != nil {
		log.Println(err)
		return err
	}
	fmt.Println(resp.TLS)
	return err
}
<commit_msg>add wg for go routines<commit_after>package main

import (
	"bufio"
	"compress/gzip"
	"crypto/tls"
	"encoding/csv"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
)

type Domain struct {
	Name     string
	Reg      string
	Create   string
	PaidTill string
	FreeDate string
	TLSVer   string
}

// TODO: rewrite this sheet to reflect
func (d Domain) Write() []string {
	s := []string{d.Name, d.TLSVer}
	return s
}

func main() {
	var (
		zones [1]string
		err   error
	)
	const (
		workers = 200
	)
	zones[0] = "ru"

	zoneUrl := fmt.Sprintf("https://partner.r01.ru/zones/%s_domains.gz", zones[0])
	zoneFile := fmt.Sprintf("%s_zone.gz", zones[0])
	zoneFileDecompressed := fmt.Sprintf("%s_zone", zones[0])

	err = DownloadFile(zoneFile, zoneUrl)
	if err != nil {
		log.Fatal(err)
	}
	err = DecompressFile(zoneFile, zoneFileDecompressed)
	if err != nil {
		log.Fatal(err)
	}

	Domains := LoadData(zoneFileDecompressed)
	CheckTLSVersion(Domains, workers)
}

func DownloadFile(filepath string, url string) error {
	resp, err := http.Get(url)
	buf := make([]byte, 1024)
	bytesRead := 0

	if err != nil {
		return err
	}

	// Create the file
	out, err := os.Create(filepath)
	if err != nil {
		return err
	}
	defer out.Close()

	for {
		n, err := resp.Body.Read(buf)
		if err != nil {
			if err == io.EOF {
				_, err = out.Write(buf[:n])
				if err != nil {
					log.Fatal(err)
				}
				break
			}
			log.Fatal(err)
		}
		_, err = out.Write(buf[:n])
		if err != nil {
			log.Fatal(err)
		}
		bytesRead += n
	}
	defer resp.Body.Close()
	return err
}

func DecompressFile(gzipped string, ungzipped string) error {
	buf := make([]byte, 1024)
	input, err := os.Open(gzipped)
	if err != nil {
		log.Fatal(err)
	}
	r, err := gzip.NewReader(input)
	if err != nil {
		log.Fatal(err)
	}
	out, _ := os.Create(ungzipped)
	for {
		n, err := r.Read(buf)
		if err != nil {
			if err == io.EOF {
				_, err = out.Write(buf[:n])
				if err != nil {
					log.Fatal(err)
				}
				break
			}
			log.Fatal(err)
		}

		fmt.Println(n)
		_, err = out.Write(buf[:n])
		if err != nil {
			log.Fatal(err)
		}

	}
	return err
}

func LoadData(dataFilePath string) []Domain {
	var Domains []Domain
	fd, err := os.Open(dataFilePath)
	if err != nil {
		log.Fatal(err)
	}

	s := bufio.NewScanner(fd)
	s.Split(bufio.ScanLines)
	for s.Scan() {
		line := strings.Fields(s.Text())
		Domains = append(Domains, Domain{line[0], line[1], line[2], line[3], line[4], ""})
	}
	return Domains
}

func CheckTLSVersion(Domains []Domain, workers int) {
	var (
		wg  sync.WaitGroup
		ch  = make(chan Domain)
		ch2 = make(chan Domain)
	)
	// create threads waiting on channel
	for i := 1; i < workers; i++ {
		wg.Add(1)
		go WrapSendRequest(ch, ch2, &wg)
	}

	// create writer to csv
	wg.Add(1)
	go WriteCSVFile(ch2)

	// Generate data and send to channel
	for i := 1; i < len(Domains); i++ {
		ch <- Domains[i]
	}
	// wait while all goroutines  will finish work
	wg.Wait()
}

func WrapSendRequest(ch chan Domain, ch2 chan Domain, wg *sync.WaitGroup) {
	// read data from channel and do staff
	for domain := range ch {
		domain = SendRequest(domain)
		ch2 <- domain
	}
	// when no data in the channel finish goroutine
	wg.Done()
}
func WriteCSVFile(ch chan Domain) {
	fd, _ := os.Create("./out.csv")
	w := csv.NewWriter(fd)
	for domain := range ch {
		w.Write(domain.Write())
		fmt.Printf("TLSVer: Domain: %s %s TLSVerEnd\n", domain.Name, domain.TLSVer)
	}
}
func SendRequest(domain Domain) Domain {
	var (
		tlsVersion string
	)
	url := fmt.Sprintf("https://%s", domain.Name)
	client := &http.Client{CheckRedirect: func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse }}
	resp, err := client.Get(url)
	if err != nil {
		//log.Println(err)
		domain.TLSVer = "Could not connect to by https"
		return domain
	}
	if resp.StatusCode == 200 {
		log.Printf("domain: %s status code: %d", domain.Name, resp.StatusCode)
		if resp.TLS.Version == tls.VersionTLS10 {
			tlsVersion = "TLS 1.0"
		} else if resp.TLS.Version == tls.VersionTLS11 {
			tlsVersion = "TLS 1.1"
		} else if resp.TLS.Version == tls.VersionTLS12 {
			tlsVersion = "TLS 1.2"
		} else if resp.TLS.Version == tls.VersionTLS13 {
			tlsVersion = "TLS 1.3"
		} else if resp.TLS.Version == tls.VersionSSL30 {
			tlsVersion = "SSLv3"
		} else {
			tlsVersion = "unknown"
		}
		domain.TLSVer = tlsVersion
	}
	return domain
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"os/exec"
	"strings"
	"testing"

	"github.com/containerops/dockyard/test"
)

func TestPullInit(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoBase := reponame + ":" + repotags[0]

	if err = exec.Command(test.DockerBinary, "inspect", repoBase).Run(); err != nil {
		cmd = exec.Command(test.DockerBinary, "pull", repoBase)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
		}
	}

	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	for _, v := range repotags {
		tag := repoDest + ":" + v
		cmd = exec.Command(test.DockerBinary, "tag", "-f", repoBase, tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Tag %v failed: [Info]%v, [Error]%v", repoBase, out, err)
		}
		cmd = exec.Command(test.DockerBinary, "push", tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Push all tags %v failed: [Info]%v, [Error]%v", tag, out, err)
		}
	}
}

func getCurrentVersion() (string, string, error) {
	cmd := exec.Command(test.DockerBinary, "-v")
	out, err := test.ParseCmdCtx(cmd)
	if err != nil {
		return "", "", fmt.Errorf("Get docker version failed")
	}

	curVer := strings.Split(strings.Split(out, ",")[0], " ")[2]
	val := test.Compare(curVer, "1.6.0")
	if val < 0 {
		return curVer, "V1", nil
	} else {
		return curVer, "V2", nil
	}
}

func chkAndDelAllRepoTags(repoBase string, repotags []string) error {
	for _, v := range repotags {
		repotag := repoBase + ":" + v
		if err := exec.Command(test.DockerBinary, "inspect", repotag).Run(); err != nil {
			return fmt.Errorf(err.Error())
		}

		cmd := exec.Command(test.DockerBinary, "rmi", repotag)
		if _, err := test.ParseCmdCtx(cmd); err != nil {
			return fmt.Errorf(err.Error())
		}
	}
	return nil
}

func TestPullRepoSingleTag(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	for i := 1; i <= 2; i++ {
		cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest+":"+repotags[0], out, err)
		}
	}

	if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
		t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
	}
}

//if there are multiple tags in registry,if protocol V2 pulling is not specified tag, default to get latest tag,different from protocol V1
func TestPullV2RepoWithoutTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	_, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if registry == "V2" {
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
			/*
				if !strings.Contains(out, "Using default tag: latest") {
					t.Fatalf("Not expected result")
				}
			*/
		}

		repotags := []string{"latest"}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}
	}
}

func TestPullRepoMultipleTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	curVer, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if !strings.Contains(curVer, "1.6") {
		//Pull Repository Multiple Tags with option "-a",protocol V1 and V2 are all the same except Docker 1.6.x
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", "-a", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}

		if registry == "V1" {
			//Docker daemon support to pull Repository Multiple Tags without option "-a"
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}

			//if there are multiple tags in registry,pull specified tag will get all tags of repository
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}
		}
	} else {
		//There is a bug about "pull -a" in Docker 1.6.x,it will be change from protocol V2 to V1 if using "pull -a"
	}
}

func TestPullNonExistentRepo(t *testing.T) {
	repoDest := test.Domains + "/" + test.UserName + "/" + "nonexistentrepo"
	cmd := exec.Command(test.DockerBinary, "pull", repoDest)
	if out, err := test.ParseCmdCtx(cmd); err == nil {
		t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
	}
}

/*
func Example_random() {
	fmt.Println("mabintest")
	//output:
	//mabintest
}
*/
<commit_msg>Modify pull Test suite<commit_after>package main

import (
	"fmt"
	"os/exec"
	"strings"
	"testing"

	"github.com/containerops/dockyard/test"
)

func TestPullInit(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoBase := reponame + ":" + repotags[0]

	if err = exec.Command(test.DockerBinary, "inspect", repoBase).Run(); err != nil {
		cmd = exec.Command(test.DockerBinary, "pull", repoBase)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
		}
	}

	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	for _, v := range repotags {
		tag := repoDest + ":" + v
		cmd = exec.Command(test.DockerBinary, "tag", "-f", repoBase, tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Tag %v failed: [Info]%v, [Error]%v", repoBase, out, err)
		}
		cmd = exec.Command(test.DockerBinary, "push", tag)
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Push all tags %v failed: [Info]%v, [Error]%v", tag, out, err)
		}
	}
}

func getCurrentVersion() (string, string, error) {
	cmd := exec.Command(test.DockerBinary, "-v")
	out, err := test.ParseCmdCtx(cmd)
	if err != nil {
		return "", "", fmt.Errorf("Get docker version failed")
	}

	curVer := strings.Split(strings.Split(out, ",")[0], " ")[2]
	val := test.Compare(curVer, "1.6.0")
	if val < 0 {
		return curVer, "V1", nil
	} else {
		return curVer, "V2", nil
	}
}

func chkAndDelAllRepoTags(repoBase string, repotags []string) error {
	for _, v := range repotags {
		repotag := repoBase + ":" + v
		if err := exec.Command(test.DockerBinary, "inspect", repotag).Run(); err != nil {
			return fmt.Errorf(err.Error())
		}

		cmd := exec.Command(test.DockerBinary, "rmi", repotag)
		if _, err := test.ParseCmdCtx(cmd); err != nil {
			return fmt.Errorf(err.Error())
		}
	}
	return nil
}

func TestPullRepoSingleTag(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	for i := 1; i <= 2; i++ {
		cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
		if out, err = test.ParseCmdCtx(cmd); err != nil {
			t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest+":"+repotags[0], out, err)
		}
	}

	if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
		t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
	}
}

//if there are multiple tags in registry,if protocol V2 pulling is not specified tag, default to get latest tag,different from protocol V1
func TestPullV2RepoWithoutTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame
	repotags := []string{"latest", "1.0", "2.0"}

	_, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if registry == "V2" {
		for _, v := range repotags {
			tag := repoDest + ":" + v
			if err = exec.Command(test.DockerBinary, "inspect", tag).Run(); err == nil {
				cmd = exec.Command(test.DockerBinary, "rmi", tag)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull testing preparation is failed: [Info]%v, [Error]%v", out, err)
				}
			}
		}

		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}

		for _, v := range repotags {
			if v != "latest" {
				tag := repoDest + ":" + v
				if err = exec.Command(test.DockerBinary, "inspect", tag).Run(); err == nil {
					t.Fatalf("Not expect result")
				}
			}
		}

		if err := chkAndDelAllRepoTags(repoDest, []string{"latest"}); err != nil {
			t.Fatalf("Pull %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}
	}
}

func TestPullRepoMultipleTags(t *testing.T) {
	var cmd *exec.Cmd
	var err error
	var out string

	reponame := "busybox"
	repotags := []string{"latest", "1.0", "2.0"}
	repoDest := test.Domains + "/" + test.UserName + "/" + reponame

	curVer, registry, err := getCurrentVersion()
	if err != nil {
		t.Fatal(err.Error())
	}

	if !strings.Contains(curVer, "1.6") {
		//Pull Repository Multiple Tags with option "-a",protocol V1 and V2 are all the same except Docker 1.6.x
		for i := 1; i <= 2; i++ {
			cmd = exec.Command(test.DockerBinary, "pull", "-a", repoDest)
			if out, err = test.ParseCmdCtx(cmd); err != nil {
				t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
			}
		}
		if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
			t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
		}

		if registry == "V1" {
			//Docker daemon support to pull Repository Multiple Tags without option "-a"
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest)
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}

			//if there are multiple tags in registry,pull specified tag will get all tags of repository
			for i := 1; i <= 2; i++ {
				cmd = exec.Command(test.DockerBinary, "pull", repoDest+":"+repotags[0])
				if out, err = test.ParseCmdCtx(cmd); err != nil {
					t.Fatalf("Pull all tags of %v failed: [Info]%v, [Error]%v", repoDest, out, err)
				}
			}
			if err := chkAndDelAllRepoTags(repoDest, repotags); err != nil {
				t.Fatalf("Pull all tags of %v failed, it is not found in location. [Error]%v", repoDest, err.Error())
			}
		}
	} else {
		//There is a bug about "pull -a" in Docker 1.6.x,it will be change from protocol V2 to V1 if using "pull -a"
	}
}

func TestPullNonExistentRepo(t *testing.T) {
	repoDest := test.Domains + "/" + test.UserName + "/" + "nonexistentrepo"
	cmd := exec.Command(test.DockerBinary, "pull", repoDest)
	if out, err := test.ParseCmdCtx(cmd); err == nil {
		t.Fatalf("Pull %v failed: [Info]%v, [Error]%v", repoDest, out, err)
	}
}

/*
func Example_random() {
	fmt.Println("mabintest")
	//output:
	//mabintest
}
*/
<|endoftext|>


<commit_before>package tracks

import (
	"sync"

	"github.com/jeremija/peer-calls/src/server-go/logger"
	"github.com/jeremija/peer-calls/src/server-go/wrtc"
	"github.com/pion/webrtc/v2"
)

var log = logger.GetLogger("tracks")

type TracksManager struct {
	mu sync.RWMutex
	// key is clientID
	peers map[string]peerInRoom
	// key is room, value is clientID
	peerIDsByRoom map[string]map[string]struct{}
}

func NewTracksManager() *TracksManager {
	return &TracksManager{
		peers:         map[string]peerInRoom{},
		peerIDsByRoom: map[string]map[string]struct{}{},
	}
}

type peerInRoom struct {
	peer      *Peer
	room      string
	signaller *wrtc.Signaller
}

func (t *TracksManager) addTrack(room string, clientID string, track *webrtc.Track) {
	t.mu.Lock()

	for otherClientID, otherPeerInRoom := range t.peers {
		// if otherClientID != clientID {
		err := otherPeerInRoom.peer.AddTrack(track)
		if err != nil {
			log.Printf("TracksManager.addTrack Error adding track: %s to clientID: %s (source clientID: %s): %s)", track.ID(), otherClientID, clientID, err)
			continue
		}

		kind := track.Kind()
		signaller := otherPeerInRoom.signaller
		log.Printf("Calling signaller.AddTransceiverRequest() and signaller.Negotiate() because a new %s track was added", kind)
		// adapter.Emit(clientID, wsmessage.NewMessage("signal", room, map[string]interface{}{
		// 	"userId": localPeerID,
		// 	"signal": map[string]interface{}{
		// 		"transceiverRequest": map[string]string{"kind": kind},
		// 	},
		// }))
		signaller.SendTransceiverRequest(kind, webrtc.RTPTransceiverDirectionRecvonly)
		signaller.Negotiate()
		// }
	}

	t.mu.Unlock()
}

func (t *TracksManager) Add(room string, clientID string, peerConnection PeerConnection, signaller *wrtc.Signaller) {
	log.Printf("Add peer to TrackManager room: %s, clientID: %s", room, clientID)

	peer := NewPeer(
		clientID,
		peerConnection,
		func(clientID string, track *webrtc.Track) {
			t.addTrack(room, clientID, track)
		},
		t.removePeer,
	)

	t.mu.Lock()
	peerJoiningRoom := peerInRoom{
		peer:      peer,
		room:      room,
		signaller: signaller,
	}

	peersSet, ok := t.peerIDsByRoom[room]
	if !ok {
		peersSet = map[string]struct{}{}
		t.peerIDsByRoom[room] = peersSet
	}

	for existingPeerClientID := range peersSet {
		existingPeerInRoom, ok := t.peers[existingPeerClientID]
		if !ok {
			log.Printf("Cannot find existing peer with clientID: %s", existingPeerClientID)
			continue
		}
		for _, track := range existingPeerInRoom.peer.Tracks() {
			err := peerJoiningRoom.peer.AddTrack(track)
			if err != nil {
				log.Printf(
					"Error adding peer clientID: %s track to clientID: %s - reason: %s",
					existingPeerClientID,
					clientID,
					err,
				)
				continue
			}
		}
	}

	t.peers[clientID] = peerJoiningRoom
	peersSet[clientID] = struct{}{}
	t.mu.Unlock()
}

func (t *TracksManager) removePeer(clientID string) {
	log.Printf("removePeer: %s", clientID)
	t.mu.Lock()
	defer t.mu.Unlock()
	peerLeavingRoom, ok := t.peers[clientID]
	if !ok {
		log.Printf("Cannot remove peer clientID: %s (not found)", clientID)
		return
	}

	t.removePeerTracks(peerLeavingRoom)

	delete(t.peers, clientID)
	peerIDs, ok := t.peerIDsByRoom[peerLeavingRoom.room]
	if !ok {
		log.Printf("Cannot remove peer ID from room: %s (not found)", clientID)
		return
	}
	delete(peerIDs, clientID)
}

func (t *TracksManager) removePeerTracks(peerLeavingRoom peerInRoom) {
	leavingClientID := peerLeavingRoom.peer.ClientID()
	log.Printf("Remove all peer tracks for clientID: %s", leavingClientID)
	clientIDs, ok := t.peerIDsByRoom[peerLeavingRoom.room]
	if !ok {
		log.Println("Cannot find any peers in room", peerLeavingRoom.room)
		return
	}

	tracks := peerLeavingRoom.peer.Tracks()
	for clientID := range clientIDs {
		if clientID != leavingClientID {
			otherPeerInRoom := t.peers[clientID]
			for _, track := range tracks {
				log.Printf(
					"Removing track: %s from peer clientID: %s (source clientID: %s)",
					track.ID(),
					clientID,
					leavingClientID,
				)
				err := otherPeerInRoom.peer.RemoveTrack(track)
				if err != nil {
					log.Printf(
						"Error removing track: %s from peer clientID: %s (source clientID: %s): %s",
						track.ID(),
						clientID,
						leavingClientID,
						err,
					)
				}
			}
		}
	}
}
<commit_msg>Do not call Negotiate() when asking initiatro to add transceiver<commit_after>package tracks

import (
	"sync"

	"github.com/jeremija/peer-calls/src/server-go/logger"
	"github.com/jeremija/peer-calls/src/server-go/wrtc"
	"github.com/pion/webrtc/v2"
)

var log = logger.GetLogger("tracks")

type TracksManager struct {
	mu sync.RWMutex
	// key is clientID
	peers map[string]peerInRoom
	// key is room, value is clientID
	peerIDsByRoom map[string]map[string]struct{}
}

func NewTracksManager() *TracksManager {
	return &TracksManager{
		peers:         map[string]peerInRoom{},
		peerIDsByRoom: map[string]map[string]struct{}{},
	}
}

type peerInRoom struct {
	peer      *Peer
	room      string
	signaller *wrtc.Signaller
}

func (t *TracksManager) addTrack(room string, clientID string, track *webrtc.Track) {
	t.mu.Lock()

	for otherClientID, otherPeerInRoom := range t.peers {
		// if otherClientID != clientID {
		err := otherPeerInRoom.peer.AddTrack(track)
		if err != nil {
			log.Printf("TracksManager.addTrack Error adding track: %s to clientID: %s (source clientID: %s): %s)", track.ID(), otherClientID, clientID, err)
			continue
		}

		kind := track.Kind()
		signaller := otherPeerInRoom.signaller
		log.Printf("Calling signaller.AddTransceiverRequest() and signaller.Negotiate() because a new %s track was added", kind)
		// adapter.Emit(clientID, wsmessage.NewMessage("signal", room, map[string]interface{}{
		// 	"userId": localPeerID,
		// 	"signal": map[string]interface{}{
		// 		"transceiverRequest": map[string]string{"kind": kind},
		// 	},
		// }))
		if signaller.Initiator() {
			signaller.Negotiate()
		} else {
			signaller.SendTransceiverRequest(kind, webrtc.RTPTransceiverDirectionRecvonly)
		}
		// }
	}

	t.mu.Unlock()
}

func (t *TracksManager) Add(room string, clientID string, peerConnection PeerConnection, signaller *wrtc.Signaller) {
	log.Printf("Add peer to TrackManager room: %s, clientID: %s", room, clientID)

	peer := NewPeer(
		clientID,
		peerConnection,
		func(clientID string, track *webrtc.Track) {
			t.addTrack(room, clientID, track)
		},
		t.removePeer,
	)

	t.mu.Lock()
	peerJoiningRoom := peerInRoom{
		peer:      peer,
		room:      room,
		signaller: signaller,
	}

	peersSet, ok := t.peerIDsByRoom[room]
	if !ok {
		peersSet = map[string]struct{}{}
		t.peerIDsByRoom[room] = peersSet
	}

	for existingPeerClientID := range peersSet {
		existingPeerInRoom, ok := t.peers[existingPeerClientID]
		if !ok {
			log.Printf("Cannot find existing peer with clientID: %s", existingPeerClientID)
			continue
		}
		for _, track := range existingPeerInRoom.peer.Tracks() {
			err := peerJoiningRoom.peer.AddTrack(track)
			if err != nil {
				log.Printf(
					"Error adding peer clientID: %s track to clientID: %s - reason: %s",
					existingPeerClientID,
					clientID,
					err,
				)
				continue
			}
		}
	}

	t.peers[clientID] = peerJoiningRoom
	peersSet[clientID] = struct{}{}
	t.mu.Unlock()
}

func (t *TracksManager) removePeer(clientID string) {
	log.Printf("removePeer: %s", clientID)
	t.mu.Lock()
	defer t.mu.Unlock()
	peerLeavingRoom, ok := t.peers[clientID]
	if !ok {
		log.Printf("Cannot remove peer clientID: %s (not found)", clientID)
		return
	}

	t.removePeerTracks(peerLeavingRoom)

	delete(t.peers, clientID)
	peerIDs, ok := t.peerIDsByRoom[peerLeavingRoom.room]
	if !ok {
		log.Printf("Cannot remove peer ID from room: %s (not found)", clientID)
		return
	}
	delete(peerIDs, clientID)
}

func (t *TracksManager) removePeerTracks(peerLeavingRoom peerInRoom) {
	leavingClientID := peerLeavingRoom.peer.ClientID()
	log.Printf("Remove all peer tracks for clientID: %s", leavingClientID)
	clientIDs, ok := t.peerIDsByRoom[peerLeavingRoom.room]
	if !ok {
		log.Println("Cannot find any peers in room", peerLeavingRoom.room)
		return
	}

	tracks := peerLeavingRoom.peer.Tracks()
	for clientID := range clientIDs {
		if clientID != leavingClientID {
			otherPeerInRoom := t.peers[clientID]
			for _, track := range tracks {
				log.Printf(
					"Removing track: %s from peer clientID: %s (source clientID: %s)",
					track.ID(),
					clientID,
					leavingClientID,
				)
				err := otherPeerInRoom.peer.RemoveTrack(track)
				if err != nil {
					log.Printf(
						"Error removing track: %s from peer clientID: %s (source clientID: %s): %s",
						track.ID(),
						clientID,
						leavingClientID,
						err,
					)
				}
			}
		}
	}
}
<|endoftext|>


<commit_before>package main

func main() {

}
<commit_msg>remove unused file<commit_after><|endoftext|>


<commit_before>//
// templates.go
// template model interfaces
//
package srnd

import (
  "fmt"
  "github.com/hoisie/mustache"
  "io"
  "io/ioutil"
  "log"
  "path/filepath"
  "sort"
  "strings"
)

type templateEngine struct {
  // every newsgroup
  groups map[string]GroupModel
  // loaded templates
  templates map[string]string
  // root directory for templates
  template_dir string
}

func (self templateEngine) templateCached(name string) (ok bool) {
  _, ok = self.templates[name]
  return
}

// explicitly reload a template
func (self templateEngine) reloadTemplate(name string) {
  self.templates[name] = self.loadTemplate(name)
}

// check if we have this template
func (self templateEngine) hasTemplate(name string) bool {
  return CheckFile(self.templateFilepath(name))
}

// explicitly reload all loaded templates
func (self templateEngine) reloadAllTemplates() {
  loadThese := []string{}
  // get all the names of the templates we have loaded
  for tname, _ := range self.templates {
    loadThese = append(loadThese, tname)
  }
  // for each template we have loaded, reload the contents from file
  for _, tname := range loadThese {
    self.templates[tname] = self.loadTemplate(tname)
  }
}

// get the filepath to a template
func (self templateEngine) templateFilepath(name string) string {
  if strings.Count(name, "..") > 0 {
    return ""
  }
  return filepath.Join(self.template_dir, name)
}

// load a template from file, return as string
func (self templateEngine) loadTemplate(name string) (t string) {
  // ignores errors, this is probably bad
  b, err := ioutil.ReadFile(self.templateFilepath(name))
  if err != nil {
    log.Println("error loading template", err)
  }
  t = string(b)
  return
}

// get a template, if it's not cached load from file and cache it
func (self templateEngine) getTemplate(name string) (t string) {
  if self.templateCached(name) {
    t, _ = self.templates[name]
  } else {
    self.templates[name] = self.loadTemplate(name)
  }
  return
}

// render a template, self explanitory
func (self templateEngine) renderTemplate(name string, obj interface{}) string {
  t := self.getTemplate(name)
  return mustache.Render(t, obj)
}

// get a board model given a newsgroup
// load un updated board model if we don't have it
func (self templateEngine) obtainBoard(prefix, frontend, group string, db Database) (model GroupModel) {
  model, ok := self.groups[group]
  // if we don't already have the board loaded load it
  if ! ok  {
    p := db.GetGroupPageCount(group)
    pages := int(p)
    // ignore error
    perpage, _ := db.GetThreadsPerPage(group)
    for page := 0 ; page < pages ; page ++ {
      model = append(model, db.GetGroupForPage(prefix, frontend, group, page, int(perpage)))
    }
    self.groups[group] = model
  }
  return

}
// generate a board page
func (self templateEngine) genBoardPage(prefix, frontend, newsgroup string, page int, outfile string, db Database) {

  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // update the board page
  board = board.Update(page, db)
  if page >= len(board) {
    log.Println("board page should not exist", newsgroup, "page", page)
    return
  }
  // render it
  wr, err := OpenFileWriter(outfile)
  if err == nil {
    board[page].RenderTo(wr)
    wr.Close()
    log.Println("wrote file", outfile)
  } else {
    log.Println("error generating board page", page, "for", newsgroup, err)
  }
  // save it
  self.groups[newsgroup] = board
}

// generate every page for a board
func (self templateEngine) genBoard(prefix, frontend, newsgroup, outdir string, db Database) {
  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // update the entire board model
  board = board.UpdateAll(db)
  // save the model
  self.groups[newsgroup] = board

  pages := len(board)
  for page := 0 ; page < pages ; page ++ {
    outfile := filepath.Join(outdir, fmt.Sprintf("%s-%d.html", newsgroup, page))
    wr, err := OpenFileWriter(outfile)
    if err == nil {
      board[page].RenderTo(wr)
      wr.Close()
      log.Println("wrote file", outfile)
    } else {
      log.Println("error generating board page", page, "for", newsgroup, err)
    }
  }
}

func (self templateEngine) genUkko(prefix, frontend, outfile string, database Database) {
  var threads []ThreadModel
  // get the last 15 bumped threads globally, for each...
  for _, article := range database.GetLastBumpedThreads("", 15) {
    // get the newsgroup and root post id
    newsgroup, msgid := article[1], article[0]
    // obtain board model
    board := self.obtainBoard(prefix, frontend, newsgroup, database)
    // update first page
    board = board.Update(0, database)
    // grab the root post in question
    th := board[0].GetThread(msgid)
    if th != nil {
        threads = append(threads, th.Update(database))
    }
    // save board model
    self.groups[newsgroup] = board
  }
  wr, err := OpenFileWriter(outfile)
  if err == nil {
    io.WriteString(wr, template.renderTemplate("ukko.mustache", map[string]interface{} { "prefix" : prefix, "threads" : threads }))
    wr.Close()
  } else {
    log.Println("error generating ukko", err)
  }
}

func (self templateEngine) genThread(root ArticleEntry, prefix, frontend, outfile string, db Database) {
  newsgroup := root.Newsgroup()
  msgid := root.MessageID()
  var th ThreadModel
  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // find the thread model in question
  for _, pagemodel := range board {
    t := pagemodel.GetThread(msgid)
    if t != nil {
      th = t
      break
    }
  }
  if th == nil {
    // wtf we don't have the thread?
    log.Println("we didn't find thread for", msgid, "did not regenerate")
  } else {
    // update thread model and write it out
    th = th.Update(db)
    wr, err := OpenFileWriter(outfile)
    if err == nil {
      th.RenderTo(wr)
      wr.Close()
      log.Println("wrote file", outfile)
    } else {
      log.Println("did not write", outfile, err)
    }
  }
  // save it
  self.groups[newsgroup] = board
}

func newTemplateEngine(dir string) *templateEngine {
  return &templateEngine{
    groups: make(map[string]GroupModel),
    templates: make(map[string]string),
    template_dir: dir,
  }
}

var template = newTemplateEngine(defaultTemplateDir())

func renderPostForm(prefix, board, op_msg_id string) string {
  url := prefix + "post/" + board
  button := "New Thread"
  if op_msg_id != "" {
    button = "Reply"
  }
  return template.renderTemplate("postform.mustache", map[string]string { "post_url" : url, "reference" : op_msg_id , "button" : button } )
}

func (self templateEngine) genFrontPage(top_count int, frontend_name, outfile string, db Database) {
  // the graph for the front page
  var frontpage_graph boardPageRows

  // for each group
  groups := db.GetAllNewsgroups()
  for idx, group := range groups {
    if idx >= top_count {
      break
    }
    // posts per hour
    hour := db.CountPostsInGroup(group, 3600)
    // posts per day
    day := db.CountPostsInGroup(group, 86400)
    // posts total
    all := db.CountPostsInGroup(group, 0)
    frontpage_graph = append(frontpage_graph, boardPageRow{
      All: all,
      Day: day,
      Hour: hour,
      Board: group,
    })
  }
  wr, err := OpenFileWriter(outfile)
  if err != nil {
    log.Println("cannot render front page", err)
    return
  }

  param := make(map[string]interface{})
  sort.Sort(frontpage_graph)
  param["graph"] = frontpage_graph
  param["frontend"] = frontend_name
  param["totalposts"] = db.ArticleCount()
  _, err = io.WriteString(wr, self.renderTemplate("frontpage.mustache", param))
  if err != nil {
    log.Println("error writing front page", err)
  }
  wr.Close()
}
<commit_msg>try fixing template loading bug<commit_after>//
// templates.go
// template model interfaces
//
package srnd

import (
  "fmt"
  "github.com/hoisie/mustache"
  "io"
  "io/ioutil"
  "log"
  "path/filepath"
  "sort"
  "strings"
)

type templateEngine struct {
  // every newsgroup
  groups map[string]GroupModel
  // loaded templates
  templates map[string]string
  // root directory for templates
  template_dir string
}

func (self templateEngine) templateCached(name string) (ok bool) {
  _, ok = self.templates[name]
  return
}

// explicitly reload a template
func (self templateEngine) reloadTemplate(name string) {
  self.templates[name] = self.loadTemplate(name)
}

// check if we have this template
func (self templateEngine) hasTemplate(name string) bool {
  return CheckFile(self.templateFilepath(name))
}

// explicitly reload all loaded templates
func (self templateEngine) reloadAllTemplates() {
  loadThese := []string{}
  // get all the names of the templates we have loaded
  for tname, _ := range self.templates {
    loadThese = append(loadThese, tname)
  }
  // for each template we have loaded, reload the contents from file
  for _, tname := range loadThese {
    self.reloadTemplate(tname)
  }
}

// get the filepath to a template
func (self templateEngine) templateFilepath(name string) string {
  if strings.Count(name, "..") > 0 {
    return ""
  }
  return filepath.Join(self.template_dir, name)
}

// load a template from file, return as string
func (self templateEngine) loadTemplate(name string) (t string) {
  b, err := ioutil.ReadFile(self.templateFilepath(name))
  if err == nil {
    t = string(b)
  } else {
    log.Println("error loading template", err)
    t = err.Error()
  }
  return
}

// get a template, if it's not cached load from file and cache it
func (self templateEngine) getTemplate(name string) (t string) {
  if self.templateCached(name) {
    t, _ = self.templates[name]
  } else {
    self.templates[name] = self.loadTemplate(name)
  }
  return
}

// render a template, self explanitory
func (self templateEngine) renderTemplate(name string, obj interface{}) string {
  t := self.getTemplate(name)
  return mustache.Render(t, obj)
}

// get a board model given a newsgroup
// load un updated board model if we don't have it
func (self templateEngine) obtainBoard(prefix, frontend, group string, db Database) (model GroupModel) {
  model, ok := self.groups[group]
  // if we don't already have the board loaded load it
  if ! ok  {
    p := db.GetGroupPageCount(group)
    pages := int(p)
    // ignore error
    perpage, _ := db.GetThreadsPerPage(group)
    for page := 0 ; page < pages ; page ++ {
      model = append(model, db.GetGroupForPage(prefix, frontend, group, page, int(perpage)))
    }
    self.groups[group] = model
  }
  return

}
// generate a board page
func (self templateEngine) genBoardPage(prefix, frontend, newsgroup string, page int, outfile string, db Database) {

  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // update the board page
  board = board.Update(page, db)
  if page >= len(board) {
    log.Println("board page should not exist", newsgroup, "page", page)
    return
  }
  // render it
  wr, err := OpenFileWriter(outfile)
  if err == nil {
    board[page].RenderTo(wr)
    wr.Close()
    log.Println("wrote file", outfile)
  } else {
    log.Println("error generating board page", page, "for", newsgroup, err)
  }
  // save it
  self.groups[newsgroup] = board
}

// generate every page for a board
func (self templateEngine) genBoard(prefix, frontend, newsgroup, outdir string, db Database) {
  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // update the entire board model
  board = board.UpdateAll(db)
  // save the model
  self.groups[newsgroup] = board

  pages := len(board)
  for page := 0 ; page < pages ; page ++ {
    outfile := filepath.Join(outdir, fmt.Sprintf("%s-%d.html", newsgroup, page))
    wr, err := OpenFileWriter(outfile)
    if err == nil {
      board[page].RenderTo(wr)
      wr.Close()
      log.Println("wrote file", outfile)
    } else {
      log.Println("error generating board page", page, "for", newsgroup, err)
    }
  }
}

func (self templateEngine) genUkko(prefix, frontend, outfile string, database Database) {
  var threads []ThreadModel
  // get the last 15 bumped threads globally, for each...
  for _, article := range database.GetLastBumpedThreads("", 15) {
    // get the newsgroup and root post id
    newsgroup, msgid := article[1], article[0]
    // obtain board model
    board := self.obtainBoard(prefix, frontend, newsgroup, database)
    // update first page
    board = board.Update(0, database)
    // grab the root post in question
    th := board[0].GetThread(msgid)
    if th != nil {
        threads = append(threads, th.Update(database))
    }
    // save board model
    self.groups[newsgroup] = board
  }
  wr, err := OpenFileWriter(outfile)
  if err == nil {
    io.WriteString(wr, template.renderTemplate("ukko.mustache", map[string]interface{} { "prefix" : prefix, "threads" : threads }))
    wr.Close()
  } else {
    log.Println("error generating ukko", err)
  }
}

func (self templateEngine) genThread(root ArticleEntry, prefix, frontend, outfile string, db Database) {
  newsgroup := root.Newsgroup()
  msgid := root.MessageID()
  var th ThreadModel
  // get the board model
  board := self.obtainBoard(prefix, frontend, newsgroup, db)
  // find the thread model in question
  for _, pagemodel := range board {
    t := pagemodel.GetThread(msgid)
    if t != nil {
      th = t
      break
    }
  }
  if th == nil {
    // wtf we don't have the thread?
    log.Println("we didn't find thread for", msgid, "did not regenerate")
  } else {
    // update thread model and write it out
    th = th.Update(db)
    wr, err := OpenFileWriter(outfile)
    if err == nil {
      th.RenderTo(wr)
      wr.Close()
      log.Println("wrote file", outfile)
    } else {
      log.Println("did not write", outfile, err)
    }
  }
  // save it
  self.groups[newsgroup] = board
}

func newTemplateEngine(dir string) *templateEngine {
  return &templateEngine{
    groups: make(map[string]GroupModel),
    templates: make(map[string]string),
    template_dir: dir,
  }
}

var template = newTemplateEngine(defaultTemplateDir())

func renderPostForm(prefix, board, op_msg_id string) string {
  url := prefix + "post/" + board
  button := "New Thread"
  if op_msg_id != "" {
    button = "Reply"
  }
  return template.renderTemplate("postform.mustache", map[string]string { "post_url" : url, "reference" : op_msg_id , "button" : button } )
}

func (self templateEngine) genFrontPage(top_count int, frontend_name, outfile string, db Database) {
  // the graph for the front page
  var frontpage_graph boardPageRows

  // for each group
  groups := db.GetAllNewsgroups()
  for idx, group := range groups {
    if idx >= top_count {
      break
    }
    // posts per hour
    hour := db.CountPostsInGroup(group, 3600)
    // posts per day
    day := db.CountPostsInGroup(group, 86400)
    // posts total
    all := db.CountPostsInGroup(group, 0)
    frontpage_graph = append(frontpage_graph, boardPageRow{
      All: all,
      Day: day,
      Hour: hour,
      Board: group,
    })
  }
  wr, err := OpenFileWriter(outfile)
  if err != nil {
    log.Println("cannot render front page", err)
    return
  }

  param := make(map[string]interface{})
  sort.Sort(frontpage_graph)
  param["graph"] = frontpage_graph
  param["frontend"] = frontend_name
  param["totalposts"] = db.ArticleCount()
  _, err = io.WriteString(wr, self.renderTemplate("frontpage.mustache", param))
  if err != nil {
    log.Println("error writing front page", err)
  }
  wr.Close()
}
<|endoftext|>


<commit_before>package cs

import (
	"fmt"
	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"net/http"
	"net/url"
	"time"
)

type SpotPrice struct {
	InstanceType string `json:"instance_type"`
	PriceLimit   string `json:"price_limit"`
}

type NodePoolInfo struct {
	NodePoolId      string        `json:"nodepool_id"`
	RegionId        common.Region `json:"region_id"`
	Name            *string       `json:"name"`
	Created         time.Time     `json:"created"`
	Updated         time.Time     `json:"updated"`
	IsDefault       *bool         `json:"is_default"`
	NodePoolType    string        `json:"type"`
	ResourceGroupId *string       `json:"resource_group_id"`
}

type ScalingGroup struct {
	VpcId                      string             `json:"vpc_id"`
	VswitchIds                 []string           `json:"vswitch_ids"`
	InstanceTypes              []string           `json:"instance_types"`
	LoginPassword              *string            `json:"login_password"`
	KeyPair                    *string            `json:"key_pair"`
	SecurityGroupId            string             `json:"security_group_id"`
	SecurityGroupIds           []string           `json:"security_group_ids"`
	SystemDiskCategory         ecs.DiskCategory   `json:"system_disk_category"`
	SystemDiskSize             *int64             `json:"system_disk_size"`
	SystemDiskPerformanceLevel *string            `json:"system_disk_performance_level"`
	SystemDiskEncryptAlgorithm *string            `json:"system_disk_encrypt_algorithm"`
	SystemDiskEncrypted        *bool              `json:"system_disk_encrypted"`
	SystemDiskKMSKeyId         *string            `json:"system_disk_kms_key_id"`
	DataDisks                  []NodePoolDataDisk `json:"data_disks"` //支持多个数据盘
	Tags                       []Tag              `json:"tags"`
	ImageId                    *string            `json:"image_id"`
	Platform                   *string            `json:"platform"`
	OSType                     *string            `json:"os_type"`
	ImageType                  *string            `json:"image_type"`
	InstanceChargeType         *string            `json:"instance_charge_type"`
	Period                     *int               `json:"period"`
	PeriodUnit                 *string            `json:"period_unit"`
	AutoRenew                  *bool              `json:"auto_renew"`
	AutoRenewPeriod            *int               `json:"auto_renew_period"`
	// spot实例
	SpotStrategy   *string     `json:"spot_strategy"`
	SpotPriceLimit []SpotPrice `json:"spot_price_limit"`

	RdsInstances   []string `json:"rds_instances"`
	ScalingPolicy  *string  `json:"scaling_policy"`
	ScalingGroupId *string  `json:"scaling_group_id"`

	WorkerSnapshotPolicyId *string `json:"worker_system_disk_snapshot_policy_id"`
	// 公网ip
	InternetChargeType      *string `json:"internet_charge_type"`
	InternetMaxBandwidthOut *int    `json:"internet_max_bandwidth_out"`
	// Operating system hardening
	SocEnabled *bool `json:"soc_enabled"`
	CisEnabled *bool `json:"cis_enabled"`
	// ipv6
	SupportIPv6 *bool `json:"support_ipv6"`
	// deploymentset
	DeploymentSetId *string `json:"deploymentset_id"`
	DesiredSize     *int64  `json:"desired_size,omitempty"`
}

type AutoScaling struct {
	Enable       *bool   `json:"enable"`
	MaxInstances *int64  `json:"max_instances"`
	MinInstances *int64  `json:"min_instances"`
	Type         *string `json:"type"`
	// eip
	IsBindEip *bool `json:"is_bond_eip"`
	// value: PayByBandwidth / PayByTraffic
	EipInternetChargeType *string `json:"eip_internet_charge_type"`
	// default 5
	EipBandWidth *int64 `json:"eip_bandwidth"`
}

type KubernetesConfig struct {
	NodeNameMode string  `json:"node_name_mode"`
	Taints       []Taint `json:"taints"`
	Labels       []Label `json:"labels"`
	CpuPolicy    string  `json:"cpu_policy"`
	UserData     *string `json:"user_data"`

	Runtime           string `json:"runtime,omitempty"`
	RuntimeVersion    string `json:"runtime_version"`
	CmsEnabled        *bool  `json:"cms_enabled"`
	OverwriteHostname *bool  `json:"overwrite_hostname"`
	Unschedulable     *bool  `json:"unschedulable"`
}

// 加密计算节点池
type TEEConfig struct {
	TEEType   string `json:"tee_type"`
	TEEEnable bool   `json:"tee_enable"`
}

// 托管节点池配置
type Management struct {
	Enable      *bool       `json:"enable"`
	AutoRepair  *bool       `json:"auto_repair"`
	UpgradeConf UpgradeConf `json:"upgrade_config"`
}

type UpgradeConf struct {
	AutoUpgrade       *bool  `json:"auto_upgrade"`
	Surge             *int64 `json:"surge"`
	SurgePercentage   *int64 `json:"surge_percentage,omitempty"`
	MaxUnavailable    *int64 `json:"max_unavailable"`
	KeepSurgeOnFailed *bool  `json:"keep_surge_on_failed"`
}

type CreateNodePoolRequest struct {
	RegionId         common.Region `json:"region_id"`
	Count            int64         `json:"count"`
	NodePoolInfo     `json:"nodepool_info"`
	ScalingGroup     `json:"scaling_group"`
	KubernetesConfig `json:"kubernetes_config"`
	AutoScaling      `json:"auto_scaling"`
	TEEConfig        `json:"tee_config"`
	Management       `json:"management"`
}

type BasicNodePool struct {
	NodePoolInfo   `json:"nodepool_info"`
	NodePoolStatus `json:"status"`
}

type NodePoolStatus struct {
	TotalNodes   int `json:"total_nodes"`
	OfflineNodes int `json:"offline_nodes"`
	ServingNodes int `json:"serving_nodes"`
	//DesiredNodes int  `json:"desired_nodes"`
	RemovingNodes int    `json:"removing_nodes"`
	FailedNodes   int    `json:"failed_nodes"`
	InitialNodes  int    `json:"initial_nodes"`
	HealthyNodes  int    `json:"healthy_nodes"`
	State         string `json:"state"`
}

type NodePoolDetail struct {
	BasicNodePool
	KubernetesConfig `json:"kubernetes_config"`
	ScalingGroup     `json:"scaling_group"`
	AutoScaling      `json:"auto_scaling"`
	TEEConfig        `json:"tee_config"`
	Management       `json:"management"`
}

type CreateNodePoolResponse struct {
	Response
	NodePoolID string `json:"nodepool_id"`
	Message    string `json:"Message"`
	TaskID     string `json:"task_id"`
}

type UpdateNodePoolRequest struct {
	RegionId         common.Region `json:"region_id"`
	Count            int64         `json:"count"`
	NodePoolInfo     `json:"nodepool_info"`
	ScalingGroup     `json:"scaling_group"`
	KubernetesConfig `json:"kubernetes_config"`
	AutoScaling      `json:"auto_scaling"`
	Management       `json:"management"`
}

type NodePoolsDetail struct {
	Response
	NodePools []NodePoolDetail `json:"nodepools"`
}

func (client *Client) CreateNodePool(request *CreateNodePoolRequest, clusterId string) (*CreateNodePoolResponse, error) {
	response := &CreateNodePoolResponse{}
	err := client.Invoke(request.RegionId, http.MethodPost, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, request, response)
	if err != nil {
		return nil, err
	}

	return response, nil
}

func (client *Client) DescribeNodePoolDetail(clusterId, nodePoolId string) (*NodePoolDetail, error) {
	nodePool := &NodePoolDetail{}
	err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nodePool)
	if err != nil {
		return nil, err
	}
	return nodePool, nil
}

func (client *Client) DescribeClusterNodePools(clusterId string) (*[]NodePoolDetail, error) {
	nodePools := &NodePoolsDetail{}
	err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, nil, nodePools)
	if err != nil {
		return nil, err
	}
	return &nodePools.NodePools, nil
}

func (client *Client) UpdateNodePool(clusterId string, nodePoolId string, request *UpdateNodePoolRequest) (*Response, error) {
	response := &Response{}
	err := client.Invoke(request.RegionId, http.MethodPut, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, request, response)
	if err != nil {
		return nil, err
	}

	return response, nil
}

//Deprecated
func (client *Client) DeleteNodePool(clusterId, nodePoolId string) error {
	return client.Invoke("", http.MethodDelete, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nil)
}

func (client *Client) ForceDeleteNodePool(clusterId, nodePoolId string) error {
	query := url.Values{}
	query.Add("force", "true")
	return client.Invoke("", http.MethodDelete, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), query, nil, nil)
}
<commit_msg>nodepool support kubelet params<commit_after>package cs

import (
	"fmt"
	"github.com/denverdino/aliyungo/common"
	"github.com/denverdino/aliyungo/ecs"
	"net/http"
	"net/url"
	"time"
)

type SpotPrice struct {
	InstanceType string `json:"instance_type"`
	PriceLimit   string `json:"price_limit"`
}

type NodePoolInfo struct {
	NodePoolId      string        `json:"nodepool_id"`
	RegionId        common.Region `json:"region_id"`
	Name            *string       `json:"name"`
	Created         time.Time     `json:"created"`
	Updated         time.Time     `json:"updated"`
	IsDefault       *bool         `json:"is_default"`
	NodePoolType    string        `json:"type"`
	ResourceGroupId *string       `json:"resource_group_id"`
}

type ScalingGroup struct {
	VpcId                      string             `json:"vpc_id"`
	VswitchIds                 []string           `json:"vswitch_ids"`
	InstanceTypes              []string           `json:"instance_types"`
	LoginPassword              *string            `json:"login_password"`
	KeyPair                    *string            `json:"key_pair"`
	SecurityGroupId            string             `json:"security_group_id"`
	SecurityGroupIds           []string           `json:"security_group_ids"`
	SystemDiskCategory         ecs.DiskCategory   `json:"system_disk_category"`
	SystemDiskSize             *int64             `json:"system_disk_size"`
	SystemDiskPerformanceLevel *string            `json:"system_disk_performance_level"`
	SystemDiskEncryptAlgorithm *string            `json:"system_disk_encrypt_algorithm"`
	SystemDiskEncrypted        *bool              `json:"system_disk_encrypted"`
	SystemDiskKMSKeyId         *string            `json:"system_disk_kms_key_id"`
	DataDisks                  []NodePoolDataDisk `json:"data_disks"` //支持多个数据盘
	Tags                       []Tag              `json:"tags"`
	ImageId                    *string            `json:"image_id"`
	Platform                   *string            `json:"platform"`
	OSType                     *string            `json:"os_type"`
	ImageType                  *string            `json:"image_type"`
	InstanceChargeType         *string            `json:"instance_charge_type"`
	Period                     *int               `json:"period"`
	PeriodUnit                 *string            `json:"period_unit"`
	AutoRenew                  *bool              `json:"auto_renew"`
	AutoRenewPeriod            *int               `json:"auto_renew_period"`
	// spot实例
	SpotStrategy   *string     `json:"spot_strategy"`
	SpotPriceLimit []SpotPrice `json:"spot_price_limit"`

	RdsInstances   []string `json:"rds_instances"`
	ScalingPolicy  *string  `json:"scaling_policy"`
	ScalingGroupId *string  `json:"scaling_group_id"`

	WorkerSnapshotPolicyId *string `json:"worker_system_disk_snapshot_policy_id"`
	// 公网ip
	InternetChargeType      *string `json:"internet_charge_type"`
	InternetMaxBandwidthOut *int    `json:"internet_max_bandwidth_out"`
	// Operating system hardening
	SocEnabled *bool `json:"soc_enabled"`
	CisEnabled *bool `json:"cis_enabled"`
	// ipv6
	SupportIPv6 *bool `json:"support_ipv6"`
	// deploymentset
	DeploymentSetId *string `json:"deploymentset_id"`
	DesiredSize     *int64  `json:"desired_size,omitempty"`
}

type AutoScaling struct {
	Enable       *bool   `json:"enable"`
	MaxInstances *int64  `json:"max_instances"`
	MinInstances *int64  `json:"min_instances"`
	Type         *string `json:"type"`
	// eip
	IsBindEip *bool `json:"is_bond_eip"`
	// value: PayByBandwidth / PayByTraffic
	EipInternetChargeType *string `json:"eip_internet_charge_type"`
	// default 5
	EipBandWidth *int64 `json:"eip_bandwidth"`
}

type KubernetesConfig struct {
	NodeNameMode string  `json:"node_name_mode"`
	Taints       []Taint `json:"taints"`
	Labels       []Label `json:"labels"`
	CpuPolicy    string  `json:"cpu_policy"`
	UserData     *string `json:"user_data"`

	Runtime           string `json:"runtime,omitempty"`
	RuntimeVersion    string `json:"runtime_version"`
	CmsEnabled        *bool  `json:"cms_enabled"`
	OverwriteHostname *bool  `json:"overwrite_hostname"`
	Unschedulable     *bool  `json:"unschedulable"`
}

// 加密计算节点池
type TEEConfig struct {
	TEEType   string `json:"tee_type"`
	TEEEnable bool   `json:"tee_enable"`
}

// 托管节点池配置
type Management struct {
	Enable      *bool       `json:"enable"`
	AutoRepair  *bool       `json:"auto_repair"`
	UpgradeConf UpgradeConf `json:"upgrade_config"`
}

type UpgradeConf struct {
	AutoUpgrade       *bool  `json:"auto_upgrade"`
	Surge             *int64 `json:"surge"`
	SurgePercentage   *int64 `json:"surge_percentage,omitempty"`
	MaxUnavailable    *int64 `json:"max_unavailable"`
	KeepSurgeOnFailed *bool  `json:"keep_surge_on_failed"`
}

type NodeConfig struct {
	KubeletConfiguration `json:"kubelet_configuration,omitempty"`
	RolloutPolicy        `json:"rollout_policy,omitempty"`
}

type KubeletConfiguration struct {
	CpuManagerPolicy        *string                `json:"cpuManagerPolicy,omitempty"`
	EventBurst              *int64                 `json:"eventBurst,omitempty"`
	EventRecordQPS          *int64                 `json:"eventRecordQPS,omitempty"`
	EvictionHard            map[string]interface{} `json:"evictionHard,omitempty"`
	EvictionSoft            map[string]interface{} `json:"evictionSoft,omitempty"`
	EvictionSoftGracePeriod map[string]interface{} `json:"evictionSoftGracePeriod,omitempty"`
	KubeAPIBurst            *int64                 `json:"kubeAPIBurst,omitempty"`
	KubeAPIQPS              *int64                 `json:"kubeAPIQPS,omitempty"`
	KubeReserved            map[string]interface{} `json:"kubeReserved,omitempty"`
	RegistryBurst           *int64                 `json:"registryBurst,omitempty"`
	RegistryPullQPS         *int64                 `json:"registryPullQPS,omitempty"`
	SerializeImagePulls     *bool                  `json:"serializeImagePulls,omitempty"`
	SystemReserved          map[string]interface{} `json:"systemReserved,omitempty"`
}

type RolloutPolicy struct {
	MaxUnavailable *int64 `json:"max_unavailable,omitempty"`
}

type CreateNodePoolRequest struct {
	RegionId         common.Region `json:"region_id"`
	Count            int64         `json:"count"`
	NodePoolInfo     `json:"nodepool_info"`
	ScalingGroup     `json:"scaling_group"`
	KubernetesConfig `json:"kubernetes_config"`
	AutoScaling      `json:"auto_scaling"`
	TEEConfig        `json:"tee_config"`
	Management       `json:"management"`
	NodeConfig       `json:"node_config,omitempty"`
}

type BasicNodePool struct {
	NodePoolInfo   `json:"nodepool_info"`
	NodePoolStatus `json:"status"`
}

type NodePoolStatus struct {
	TotalNodes   int `json:"total_nodes"`
	OfflineNodes int `json:"offline_nodes"`
	ServingNodes int `json:"serving_nodes"`
	//DesiredNodes int  `json:"desired_nodes"`
	RemovingNodes int    `json:"removing_nodes"`
	FailedNodes   int    `json:"failed_nodes"`
	InitialNodes  int    `json:"initial_nodes"`
	HealthyNodes  int    `json:"healthy_nodes"`
	State         string `json:"state"`
}

type NodePoolDetail struct {
	BasicNodePool
	KubernetesConfig `json:"kubernetes_config"`
	ScalingGroup     `json:"scaling_group"`
	AutoScaling      `json:"auto_scaling"`
	TEEConfig        `json:"tee_config"`
	Management       `json:"management"`
}

type CreateNodePoolResponse struct {
	Response
	NodePoolID string `json:"nodepool_id"`
	Message    string `json:"Message"`
	TaskID     string `json:"task_id"`
}

type UpdateNodePoolRequest struct {
	RegionId         common.Region `json:"region_id"`
	Count            int64         `json:"count"`
	NodePoolInfo     `json:"nodepool_info"`
	ScalingGroup     `json:"scaling_group"`
	KubernetesConfig `json:"kubernetes_config"`
	AutoScaling      `json:"auto_scaling"`
	Management       `json:"management"`
	NodeConfig       `json:"node_config,omitempty"`
}

type NodePoolsDetail struct {
	Response
	NodePools []NodePoolDetail `json:"nodepools"`
}

func (client *Client) CreateNodePool(request *CreateNodePoolRequest, clusterId string) (*CreateNodePoolResponse, error) {
	response := &CreateNodePoolResponse{}
	err := client.Invoke(request.RegionId, http.MethodPost, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, request, response)
	if err != nil {
		return nil, err
	}

	return response, nil
}

func (client *Client) DescribeNodePoolDetail(clusterId, nodePoolId string) (*NodePoolDetail, error) {
	nodePool := &NodePoolDetail{}
	err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nodePool)
	if err != nil {
		return nil, err
	}
	return nodePool, nil
}

func (client *Client) DescribeClusterNodePools(clusterId string) (*[]NodePoolDetail, error) {
	nodePools := &NodePoolsDetail{}
	err := client.Invoke("", http.MethodGet, fmt.Sprintf("/clusters/%s/nodepools", clusterId), nil, nil, nodePools)
	if err != nil {
		return nil, err
	}
	return &nodePools.NodePools, nil
}

func (client *Client) UpdateNodePool(clusterId string, nodePoolId string, request *UpdateNodePoolRequest) (*Response, error) {
	response := &Response{}
	err := client.Invoke(request.RegionId, http.MethodPut, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, request, response)
	if err != nil {
		return nil, err
	}

	return response, nil
}

//Deprecated
func (client *Client) DeleteNodePool(clusterId, nodePoolId string) error {
	return client.Invoke("", http.MethodDelete, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), nil, nil, nil)
}

func (client *Client) ForceDeleteNodePool(clusterId, nodePoolId string) error {
	query := url.Values{}
	query.Add("force", "true")
	return client.Invoke("", http.MethodDelete, fmt.Sprintf("/clusters/%s/nodepools/%s", clusterId, nodePoolId), query, nil, nil)
}
<|endoftext|>


<commit_before>package hashtree

import "github.com/pachyderm/pachyderm/src/client/pfs"

type HashTree interface {
	GetFile(path string) *FileNode
	PutFile(path string, blockRefs []*pfs.BlockRef) error
	ListFile(path string) []*FileNode
	GlobFile(pattern string) []*Node
}
<commit_msg>Add some error types<commit_after>package hashtree

import (
	"errors"

	"github.com/pachyderm/pachyderm/src/client/pfs"
)

var (
	PathNotFoundErr  = errors.New("path not found")
	MalformedGlobErr = errors.New("glob pattern malformed")
	// this error is returned when of the following occurs:
	// 1. PutFile is called with a path that points to a directory.
	// 2. PutFile is called with a path that contains a prefix that
	// points to a file.
	PathConflictErr = errors.New("path conflict")
)

type HashTree interface {
	GetFile(path string) (*FileNode, error)
	PutFile(path string, blockRefs []*pfs.BlockRef) error
	ListFile(path string) ([]*FileNode, error)
	GlobFile(pattern string) ([]*Node, error)
}
<|endoftext|>


<commit_before>package cl11

import (
	"bytes"
	"io"
	"testing"
)

func TestMappedBufferRead(t *testing.T) {
	allDevices := getDevices(t)
	for _, device := range allDevices {
		t.Log(device.Name, "on", device.Platform.Name)

		var toRelease []Object
		size := 1024 * 1024

		ctx, err := CreateContext([]*Device{device}, nil, nil, nil)
		if err != nil {
			t.Error(err)
			continue
		}
		toRelease = append(toRelease, ctx)

		cq, err := ctx.CreateCommandQueue(device, 0)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, cq)

		device0, err := ctx.CreateDeviceBuffer(int64(size), MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, device0)

		map0, err := cq.EnqueueMapBuffer(device0, Blocking, MapRead, 0, int64(size), nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		// Read nothing.
		var nothing []byte
		n, err := map0.Read(nothing)
		if n != 0 || err != nil {
			t.Error("reading nothing: want 0 <nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read everything.
		everything := make([]byte, size)
		n, err = map0.Read(everything)
		if n != size || err != nil {
			t.Error("reading everything: want", size, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read past end.
		n, err = map0.Read(everything)
		if n != 0 || err != io.EOF {
			t.Error("reading past end of buffer: want 0 io.EOF, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Reset relative to start.
		nn, err := map0.Seek(0, 0)
		if nn != 0 || err != nil {
			t.Error("seeking: want 0 <nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Write to, the full buffer.
		var buf bytes.Buffer
		nn, err = map0.WriteTo(&buf)
		if nn != int64(size) || err != nil {
			t.Error("writing to: want", size, "<nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Write to, but buffers already consumed.
		nn, err = map0.WriteTo(&buf)
		if nn != 0 || err != nil {
			t.Error("writing to: want 0 <nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at everything.
		n, err = map0.ReadAt(everything, 0)
		if n != size || err != nil {
			t.Error("read at 0 everything: want", size, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at running past end of buffer.
		n, err = map0.ReadAt(everything, 1)
		if n != size-1 || err != io.EOF {
			t.Error("read at 0 everything: want", size-1, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at starting past the end of the buffer.
		n, err = map0.ReadAt(everything, int64(size))
		if n != 0 || err != io.EOF {
			t.Error("read at 0 everything: want 0 io.EOF, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at starting at a negative value.
		n, err = map0.ReadAt(everything, -1)
		if n != 0 || err == nil {
			t.Error("read at 0 everything: want 0 cl: MappedBuffer.ReadAt: negative offset, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error("failed to unmap buffer")
			releaseAll(toRelease, t)
			continue
		}

		releaseAll(toRelease, t)
	}
}
<commit_msg>Fixed typo in test error message.<commit_after>package cl11

import (
	"bytes"
	"io"
	"testing"
)

func TestMappedBufferRead(t *testing.T) {
	allDevices := getDevices(t)
	for _, device := range allDevices {
		t.Log(device.Name, "on", device.Platform.Name)

		var toRelease []Object
		size := 1024 * 1024

		ctx, err := CreateContext([]*Device{device}, nil, nil, nil)
		if err != nil {
			t.Error(err)
			continue
		}
		toRelease = append(toRelease, ctx)

		cq, err := ctx.CreateCommandQueue(device, 0)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, cq)

		device0, err := ctx.CreateDeviceBuffer(int64(size), MemReadWrite)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}
		toRelease = append(toRelease, device0)

		map0, err := cq.EnqueueMapBuffer(device0, Blocking, MapRead, 0, int64(size), nil, nil)
		if err != nil {
			t.Error(err)
			releaseAll(toRelease, t)
			continue
		}

		// Read nothing.
		var nothing []byte
		n, err := map0.Read(nothing)
		if n != 0 || err != nil {
			t.Error("reading nothing: want 0 <nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read everything.
		everything := make([]byte, size)
		n, err = map0.Read(everything)
		if n != size || err != nil {
			t.Error("reading everything: want", size, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read past end.
		n, err = map0.Read(everything)
		if n != 0 || err != io.EOF {
			t.Error("reading past end of buffer: want 0 io.EOF, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Reset relative to start.
		nn, err := map0.Seek(0, 0)
		if nn != 0 || err != nil {
			t.Error("seeking: want 0 <nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Write to, the full buffer.
		var buf bytes.Buffer
		nn, err = map0.WriteTo(&buf)
		if nn != int64(size) || err != nil {
			t.Error("writing to: want", size, "<nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Write to, but buffers already consumed.
		nn, err = map0.WriteTo(&buf)
		if nn != 0 || err != nil {
			t.Error("writing to: want 0 <nil>, got", nn, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at everything.
		n, err = map0.ReadAt(everything, 0)
		if n != size || err != nil {
			t.Error("read at 0 everything: want", size, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at running past end of buffer.
		n, err = map0.ReadAt(everything, 1)
		if n != size-1 || err != io.EOF {
			t.Error("read at 0 everything: want", size-1, "<nil>, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at starting past the end of the buffer.
		n, err = map0.ReadAt(everything, int64(size))
		if n != 0 || err != io.EOF {
			t.Error("read at 0 everything: want 0 io.EOF, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		// Read at starting at a negative value.
		n, err = map0.ReadAt(everything, -1)
		if n != 0 || err == nil {
			t.Error("read at -1 everything: want 0 cl: MappedBuffer.ReadAt: negative offset, got", n, err)
			releaseAll(toRelease, t)
			continue
		}

		err = cq.EnqueueUnmapBuffer(map0, nil, nil)
		if err != nil {
			t.Error("failed to unmap buffer")
			releaseAll(toRelease, t)
			continue
		}

		releaseAll(toRelease, t)
	}
}
<|endoftext|>