<commit_before>// client_test.go - Katzenpost client library tests.
// Copyright (C) 2019  David Stainton.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package client provides a Katzenpost client library.
package client

import (
	"sync"
	"testing"
	"time"

	"github.com/katzenpost/kimchi"
	"github.com/stretchr/testify/require"
)

const basePort = 30000

// TestClientConnect tests that a client can connect and send a message to the loop service
func TestClientConnect(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+400, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestClientConnect.")
	k.Run()

	go func() {
		defer k.Shutdown()

		// create a client configuration
		cfg, username, linkKey, err := k.GetClientConfig()
		require.NoError(err)
		require.NotNil(cfg)

		<-time.After(90 * time.Second) // must wait for provider to fetch pki document
		t.Logf("Time is up!")

		// instantiate a client instance
		c, err := New(cfg)
		require.NotNil(cfg)
		require.NoError(err)

		// add client log output
		go k.LogTailer(username, cfg.Logging.File)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)

		// send a message
		t.Logf("desc.Provider: %s", desc.Provider)
		mesgID, err := s.SendUnreliableMessage(desc.Name, desc.Provider, []byte("hello!"))
		require.NoError(err)
		_, err = s.WaitForReply(mesgID)
		require.NoError(err)
		t.Logf("Sent unreliable message to loop service")

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()

	k.Wait()
	t.Logf("Terminated.")
}

// TestAutoRegisterRandomClient tests client registration
func TestAutoRegisterRandomClient(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+500, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestAutoRegisterRandomClient.")
	k.Run()

	go func() {
		defer k.Shutdown()
		<-time.After(70 * time.Second) // must wait for provider to fetch pki document
		cfg, err := k.GetClientNetconfig()
		require.NoError(err)

		_, linkKey := AutoRegisterRandomClient(cfg)
		require.NotNil(linkKey)

		// Verify that the client can connect
		c, err := New(cfg)
		require.NoError(err)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)
		t.Logf("Found %v kaetzchen on %v", desc.Name, desc.Provider)

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()
	k.Wait()
}

// TestDecoyClient tests client with Decoy traffic enabled
func TestDecoyClient(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+500, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestAutoRegisterRandomClient.")
	k.Run()

	go func() {
		defer k.Shutdown()
		<-time.After(70 * time.Second) // must wait for provider to fetch pki document
		cfg, err := k.GetClientNetconfig()
		require.NoError(err)
		cfg.Debug.DisableDecoyTraffic = false

		_, linkKey := AutoRegisterRandomClient(cfg)
		require.NotNil(linkKey)

		// Verify that the client can connect
		c, err := New(cfg)
		require.NoError(err)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)
		t.Logf("Found %v kaetzchen on %v", desc.Name, desc.Provider)

		wg := &sync.WaitGroup{}
		for i := 0; i < 10; i++ {
			wg.Add(1)
			go func() {
				t.Logf("SendUnreliableMessage()")
				mesgID, err := s.SendUnreliableMessage(desc.Name, desc.Provider, []byte("hello!"))
				require.NoError(err)
				_, err = s.WaitForReply(mesgID)
				require.NoError(err)
				wg.Done()
			}()
		}
		wg.Wait()

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()
	k.Wait()
}
<commit_msg>Make the tests compile<commit_after>// client_test.go - Katzenpost client library tests.
// Copyright (C) 2019  David Stainton.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// Package client provides a Katzenpost client library.
package client

import (
	"sync"
	"testing"
	"time"

	"github.com/katzenpost/kimchi"
	"github.com/stretchr/testify/require"
)

const basePort = 30000

// TestClientConnect tests that a client can connect and send a message to the loop service
func TestClientConnect(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+400, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestClientConnect.")
	k.Run()

	go func() {
		defer k.Shutdown()

		// create a client configuration
		cfg, username, linkKey, err := k.GetClientConfig()
		require.NoError(err)
		require.NotNil(cfg)

		<-time.After(90 * time.Second) // must wait for provider to fetch pki document
		t.Logf("Time is up!")

		// instantiate a client instance
		c, err := New(cfg)
		require.NotNil(cfg)
		require.NoError(err)

		// add client log output
		go k.LogTailer(username, cfg.Logging.File)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)

		// send a message
		t.Logf("desc.Provider: %s", desc.Provider)
		_, err = s.BlockingSendUnreliableMessage(desc.Name, desc.Provider, []byte("hello!"))
		require.NoError(err)
		t.Logf("Sent unreliable message to loop service")

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()

	k.Wait()
	t.Logf("Terminated.")
}

// TestAutoRegisterRandomClient tests client registration
func TestAutoRegisterRandomClient(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+500, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestAutoRegisterRandomClient.")
	k.Run()

	go func() {
		defer k.Shutdown()
		<-time.After(70 * time.Second) // must wait for provider to fetch pki document
		cfg, err := k.GetClientNetconfig()
		require.NoError(err)

		_, linkKey := AutoRegisterRandomClient(cfg)
		require.NotNil(linkKey)

		// Verify that the client can connect
		c, err := New(cfg)
		require.NoError(err)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)
		t.Logf("Found %v kaetzchen on %v", desc.Name, desc.Provider)

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()
	k.Wait()
}

// TestDecoyClient tests client with Decoy traffic enabled
func TestDecoyClient(t *testing.T) {
	require := require.New(t)
	voting := false
	nVoting := 0
	nProvider := 2
	nMix := 6
	k := kimchi.NewKimchi(basePort+500, "", nil, voting, nVoting, nProvider, nMix)
	t.Logf("Running TestAutoRegisterRandomClient.")
	k.Run()

	go func() {
		defer k.Shutdown()
		<-time.After(70 * time.Second) // must wait for provider to fetch pki document
		cfg, err := k.GetClientNetconfig()
		require.NoError(err)
		cfg.Debug.DisableDecoyTraffic = false

		_, linkKey := AutoRegisterRandomClient(cfg)
		require.NotNil(linkKey)

		// Verify that the client can connect
		c, err := New(cfg)
		require.NoError(err)

		// instantiate a session
		s, err := c.NewSession(linkKey)
		require.NoError(err)

		// look up a well known service
		desc, err := s.GetService("loop")
		require.NoError(err)
		t.Logf("Found %v kaetzchen on %v", desc.Name, desc.Provider)

		wg := &sync.WaitGroup{}
		for i := 0; i < 10; i++ {
			wg.Add(1)
			go func() {
				t.Logf("SendUnreliableMessage()")
				_, err := s.BlockingSendUnreliableMessage(desc.Name, desc.Provider, []byte("hello!"))
				require.NoError(err)
				wg.Done()
			}()
		}
		wg.Wait()

		c.Shutdown()
		t.Logf("Shutdown requested")
		c.Wait()
	}()
	k.Wait()
}
<|endoftext|>


<commit_before>package alidayu_test

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/northbright/alidayu"
)

var (
	MyAppKey    string = "" // App Key.
	MyAppSecret string = "" // App Secret.
	// Send Verification Code in SMS.
	MySignName     string = "注册验证" // SMS Sign Name. Ex: "注册验证".
	MyTemplateCode string = ""     // SMS Template Code. Ex: "SMS_XXXXXX".
	MyPhoneNumber  string = ""     // Phone number to send SMS. Ex: "13800138000".
	// Send Verification Code in Single Call.
	MyShowNumber string = "" // Show Number. Ex: "051XXXXXX".
	MyTTSCode    string = "" // TTS Code. Ex: "TTS_XXXXXXX".
)

func Example() {
	// Create a new client.
	c := &alidayu.Client{AppKey: MyAppKey, AppSecret: MyAppSecret, UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS.
	// ---------------------------------------

	// Set Parameters.
	params := map[string]string{}
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS.
	params["sms_type"] = "normal"                                 // Set SMS type.
	params["sms_free_sign_name"] = MySignName                     // Set SMS signature.
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template.
	params["sms_template_code"] = MyTemplateCode                  // Set SMS template code.
	params["rec_num"] = MyPhoneNumber                             // Set phone number to send SMS.

	// Call Post() to post the request.
	resp, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data))

	// ------------------------------------------
	// Send Verification Code in Single Call.
	// ------------------------------------------

	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call.
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template.
	params["called_num"] = MyPhoneNumber                          // Set phone number to make single call.
	params["called_show_num"] = MyShowNumber                      // Set show number.
	params["tts_code"] = MyTTSCode                                // Set TTS code.

	// Call Post() to post the request.
	resp2, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp2.Body.Close()
	data2, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data2))

	// Output:
}
<commit_msg>Add ExampleClient_Post() and ExampleClient_Exec()<commit_after>package alidayu_test

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/northbright/alidayu"
)

func ExampleClient_Post() {
	var (
		MyAppKey    string = "" // App Key.
		MyAppSecret string = "" // App Secret.
		// Send Verification Code in SMS.
		MySignName     string = "注册验证" // SMS Sign Name. Ex: "注册验证".
		MyTemplateCode string = ""     // SMS Template Code. Ex: "SMS_XXXXXX".
		MyPhoneNumber  string = ""     // Phone number to send SMS. Ex: "13800138000".
		// Send Verification Code in Single Call.
		MyShowNumber string = "" // Show Number. Ex: "051XXXXXX".
		MyTTSCode    string = "" // TTS Code. Ex: "TTS_XXXXXXX".
	)

	// Create a new client.
	c := &alidayu.Client{AppKey: MyAppKey, AppSecret: MyAppSecret, UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS.
	// ---------------------------------------

	// Set Parameters.
	params := map[string]string{}
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS.
	params["sms_type"] = "normal"                                 // Set SMS type.
	params["sms_free_sign_name"] = MySignName                     // Set SMS signature.
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template.
	params["sms_template_code"] = MyTemplateCode                  // Set SMS template code.
	params["rec_num"] = MyPhoneNumber                             // Set phone number to send SMS.

	// Call Post() to post the request.
	resp, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data))

	// ------------------------------------------
	// Send Verification Code in Single Call.
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call.
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template.
	params["called_num"] = MyPhoneNumber                          // Set phone number to make single call.
	params["called_show_num"] = MyShowNumber                      // Set show number.
	params["tts_code"] = MyTTSCode                                // Set TTS code.

	// Call Post() to post the request.
	resp2, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp2.Body.Close()
	data2, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data2))

	// Output:
}

func ExampleCient_Exec() {
	var (
		MyAppKey    string = "" // App Key.
		MyAppSecret string = "" // App Secret.
		// Send Verification Code in SMS.
		MySignName     string = "注册验证" // SMS Sign Name. Ex: "注册验证".
		MyTemplateCode string = ""     // SMS Template Code. Ex: "SMS_XXXXXX".
		MyPhoneNumber  string = ""     // Phone number to send SMS. Ex: "13800138000".
		// Send Verification Code in Single Call.
		MyShowNumber string = "" // Show Number. Ex: "051XXXXXX".
		MyTTSCode    string = "" // TTS Code. Ex: "TTS_XXXXXXX".
	)

	// Create a new client.
	c := &alidayu.Client{AppKey: MyAppKey, AppSecret: MyAppSecret, UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS.
	// ---------------------------------------

	// Set Parameters.
	params := map[string]string{}
	params["format"] = "json"
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS.
	params["extend"] = "123456"                                   // Set callback parameter.
	params["sms_type"] = "normal"                                 // Set SMS type.
	params["sms_free_sign_name"] = MySignName                     // Set SMS signature.
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template.
	params["sms_template_code"] = MyTemplateCode                  // Set SMS template code.
	params["rec_num"] = MyPhoneNumber                             // Set phone number to send SMS.

	// Call Exec() to post the request.
	success, result, err := c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// ------------------------------------------
	// Send Verification Code in Single Call.
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call.
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template.
	params["called_num"] = MyPhoneNumber                          // Set phone number to make single call.
	params["called_show_num"] = MyShowNumber                      // Set show number.
	params["tts_code"] = MyTTSCode                                // Set TTS code.

	// Call Exec() to post the request.
	success, result, err = c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// Output:
}
<|endoftext|>


<commit_before>package alidayu_test

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/northbright/alidayu"
)

// Example of Client.Post()
func ExampleClient_Post() {
	// Create a new client(创建一个新的Client实例).
	c := &alidayu.Client{AppKey: "", AppSecret: "", UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS(发送短信验证码).
	// ---------------------------------------
	// Set Parameters.
	params := map[string]string{}
	// It'll use default common parameters if you don't set them.
	// 如果这些公共参数不设置，那么会自动使用默认值.
	// params["format"] = "json"
	// params["v"] = "2.0"
	// params["sign_method"] = "md5"
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS(API接口名称).
	params["sms_type"] = "normal"                                 // Set SMS type(短信类型).
	params["sms_free_sign_name"] = ""                             // Set SMS signature(短信签名).
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template(短信模板变量).
	params["sms_template_code"] = ""                              // Set SMS template code(短信模板ID).
	params["rec_num"] = ""                                        // Set phone number to send SMS(短信接收号码).

	// Call Post() to post the request.
	resp, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data))

	// ------------------------------------------
	// Send Verification Code in Single Call(发送文本转语音通知验证码).
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call(API接口名称).
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template(文本转语音（TTS）模板变量).
	params["called_num"] = ""                                     // Set phone number to make single call(被叫号码).
	params["called_show_num"] = ""                                // Set show number(被叫号显).
	params["tts_code"] = ""                                       // Set TTS code(TTS模板ID).

	// Call Post() to post the request.
	resp2, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp2.Body.Close()
	data2, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data2))

	// Output:
}

// Example of Client.Exec()
func ExampleClient_Exec() {
	// Create a new client.
	c := &alidayu.Client{AppKey: "", AppSecret: "", UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS(发送短信验证码).
	// ---------------------------------------
	// Set Parameters.
	params := map[string]string{}
	// It'll use default common parameters if you don't set them.
	// 如果这些公共参数不设置，那么会自动使用默认值.
	// params["format"] = "json"
	// params["v"] = "2.0"
	// params["sign_method"] = "md5"
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS(API接口名称).
	params["sms_type"] = "normal"                                 // Set SMS type(短信类型).
	params["sms_free_sign_name"] = ""                             // Set SMS signature(短信签名).
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template(短信模板变量).
	params["sms_template_code"] = ""                              // Set SMS template code(短信模板ID).
	params["rec_num"] = ""                                        // Set phone number to send SMS(短信接收号码).

	// Call Exec() to post the request.
	success, result, err := c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// ------------------------------------------
	// Send Verification Code in Single Call(发送文本转语音通知验证码).
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call(API接口名称).
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template(文本转语音（TTS）模板变量).
	params["called_num"] = ""                                     // Set phone number to make single call(被叫号码).
	params["called_show_num"] = ""                                // Set show number(被叫号显).
	params["tts_code"] = ""                                       // Set TTS code(TTS模板ID).

	// Call Exec() to post the request.
	success, result, err = c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// Output:
}
<commit_msg>Add Chinese comment: (创建一个新的Client实例)<commit_after>package alidayu_test

import (
	"fmt"
	"io/ioutil"
	"os"

	"github.com/northbright/alidayu"
)

// Example of Client.Post()
func ExampleClient_Post() {
	// Create a new client(创建一个新的Client实例).
	c := &alidayu.Client{AppKey: "", AppSecret: "", UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS(发送短信验证码).
	// ---------------------------------------
	// Set Parameters.
	params := map[string]string{}
	// It'll use default common parameters if you don't set them.
	// 如果这些公共参数不设置，那么会自动使用默认值.
	// params["format"] = "json"
	// params["v"] = "2.0"
	// params["sign_method"] = "md5"
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS(API接口名称).
	params["sms_type"] = "normal"                                 // Set SMS type(短信类型).
	params["sms_free_sign_name"] = ""                             // Set SMS signature(短信签名).
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template(短信模板变量).
	params["sms_template_code"] = ""                              // Set SMS template code(短信模板ID).
	params["rec_num"] = ""                                        // Set phone number to send SMS(短信接收号码).

	// Call Post() to post the request.
	resp, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp.Body.Close()
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data))

	// ------------------------------------------
	// Send Verification Code in Single Call(发送文本转语音通知验证码).
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call(API接口名称).
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template(文本转语音（TTS）模板变量).
	params["called_num"] = ""                                     // Set phone number to make single call(被叫号码).
	params["called_show_num"] = ""                                // Set show number(被叫号显).
	params["tts_code"] = ""                                       // Set TTS code(TTS模板ID).

	// Call Post() to post the request.
	resp2, err := c.Post(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Post() error: %v\n", err)
		return
	}

	// Read HTTP Response.
	defer resp2.Body.Close()
	data2, err := ioutil.ReadAll(resp2.Body)
	if err != nil {
		fmt.Fprintf(os.Stderr, "ioutil.ReadAll() error:%v\n", err)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Post() successfully\n%v\n", string(data2))

	// Output:
}

// Example of Client.Exec()
func ExampleClient_Exec() {
	// Create a new client(创建一个新的Client实例).
	c := &alidayu.Client{AppKey: "", AppSecret: "", UseHTTPS: false}

	// ---------------------------------------
	// Send Verification Code in SMS(发送短信验证码).
	// ---------------------------------------
	// Set Parameters.
	params := map[string]string{}
	// It'll use default common parameters if you don't set them.
	// 如果这些公共参数不设置，那么会自动使用默认值.
	// params["format"] = "json"
	// params["v"] = "2.0"
	// params["sign_method"] = "md5"
	params["method"] = "alibaba.aliqin.fc.sms.num.send"           // Set method to send SMS(API接口名称).
	params["sms_type"] = "normal"                                 // Set SMS type(短信类型).
	params["sms_free_sign_name"] = ""                             // Set SMS signature(短信签名).
	params["sms_param"] = `{"code":"123456", "product":"My App"}` // Set variable for SMS template(短信模板变量).
	params["sms_template_code"] = ""                              // Set SMS template code(短信模板ID).
	params["rec_num"] = ""                                        // Set phone number to send SMS(短信接收号码).

	// Call Exec() to post the request.
	success, result, err := c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// ------------------------------------------
	// Send Verification Code in Single Call(发送文本转语音通知验证码).
	// ------------------------------------------
	// Set Parameters.
	params = map[string]string{}
	params["method"] = "alibaba.aliqin.fc.tts.num.singlecall"     // Set method to make single call(API接口名称).
	params["tts_param"] = `{"code":"123456", "product":"My App"}` // Set variable for TTS template(文本转语音（TTS）模板变量).
	params["called_num"] = ""                                     // Set phone number to make single call(被叫号码).
	params["called_show_num"] = ""                                // Set show number(被叫号显).
	params["tts_code"] = ""                                       // Set TTS code(TTS模板ID).

	// Call Exec() to post the request.
	success, result, err = c.Exec(params)
	if err != nil {
		fmt.Fprintf(os.Stderr, "c.Exec() error: %v\nsuccess: %v\nresult: %v\n", err, success, result)
		return
	}

	fmt.Fprintf(os.Stderr, "c.Exec() successfully\nsuccess: %v\nresult: %s\n", success, result)

	// Output:
}
<|endoftext|>


<commit_before>/*
Copyright 2017 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"strings"

	"github.com/kubernetes/kompose/pkg/app"
	"github.com/kubernetes/kompose/pkg/kobject"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// TODO: comment
var (
	ConvertOut                   string
	ConvertBuildRepo             string
	ConvertBuildBranch           string
	ConvertBuild                 string
	ConvertVolumes               string
	ConvertChart                 bool
	ConvertDeployment            bool
	ConvertDaemonSet             bool
	ConvertReplicationController bool
	ConvertYaml                  bool
	ConvertJSON                  bool
	ConvertStdout                bool
	ConvertEmptyVols             bool
	ConvertInsecureRepo          bool
	ConvertDeploymentConfig      bool
	ConvertReplicas              int
	ConvertController            string
	ConvertOpt                   kobject.ConvertOptions
	ConvertYAMLIndent            int
)

var convertCmd = &cobra.Command{
	Use:   "convert [file]",
	Short: "Convert a Docker Compose file",
	PreRun: func(cmd *cobra.Command, args []string) {

		// Check that build-config wasn't passed in with --provider=kubernetes
		if GlobalProvider == "kubernetes" && UpBuild == "build-config" {
			log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
		}

		// Create the Convert Options.
		ConvertOpt = kobject.ConvertOptions{
			ToStdout:                    ConvertStdout,
			CreateChart:                 ConvertChart,
			GenerateYaml:                ConvertYaml,
			GenerateJSON:                ConvertJSON,
			Replicas:                    ConvertReplicas,
			InputFiles:                  GlobalFiles,
			OutFile:                     ConvertOut,
			Provider:                    GlobalProvider,
			CreateD:                     ConvertDeployment,
			CreateDS:                    ConvertDaemonSet,
			CreateRC:                    ConvertReplicationController,
			Build:                       ConvertBuild,
			BuildRepo:                   ConvertBuildRepo,
			BuildBranch:                 ConvertBuildBranch,
			CreateDeploymentConfig:      ConvertDeploymentConfig,
			EmptyVols:                   ConvertEmptyVols,
			Volumes:                     ConvertVolumes,
			InsecureRepository:          ConvertInsecureRepo,
			IsDeploymentFlag:            cmd.Flags().Lookup("deployment").Changed,
			IsDaemonSetFlag:             cmd.Flags().Lookup("daemon-set").Changed,
			IsReplicationControllerFlag: cmd.Flags().Lookup("replication-controller").Changed,
			Controller:                  strings.ToLower(ConvertController),
			IsReplicaSetFlag:            cmd.Flags().Lookup("replicas").Changed,
			IsDeploymentConfigFlag:      cmd.Flags().Lookup("deployment-config").Changed,
			YAMLIndent:                  ConvertYAMLIndent,
		}

		// Validate before doing anything else. Use "bundle" if passed in.
		app.ValidateFlags(GlobalBundle, args, cmd, &ConvertOpt)
		app.ValidateComposeFile(&ConvertOpt)
	},
	Run: func(cmd *cobra.Command, args []string) {

		app.Convert(ConvertOpt)
	},
}

func init() {

	// Automatically grab environment variables
	viper.AutomaticEnv()

	// Kubernetes only
	convertCmd.Flags().BoolVarP(&ConvertChart, "chart", "c", false, "Create a Helm chart for converted objects")
	convertCmd.Flags().BoolVar(&ConvertDaemonSet, "daemon-set", false, "Generate a Kubernetes daemonset object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVarP(&ConvertDeployment, "deployment", "d", false, "Generate a Kubernetes deployment object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVar(&ConvertReplicationController, "replication-controller", false, "Generate a Kubernetes replication controller object (deprecated, use --controller instead)")
	convertCmd.Flags().StringVar(&ConvertController, "controller", "", `Set the output controller ("deployment"|"daemonSet"|"replicationController")`)
	convertCmd.Flags().MarkDeprecated("daemon-set", "use --controller")
	convertCmd.Flags().MarkDeprecated("deployment", "use --controller")
	convertCmd.Flags().MarkDeprecated("replication-controller", "use --controller")
	convertCmd.Flags().MarkHidden("chart")
	convertCmd.Flags().MarkHidden("daemon-set")
	convertCmd.Flags().MarkHidden("replication-controller")
	convertCmd.Flags().MarkHidden("deployment")

	// OpenShift only
	convertCmd.Flags().BoolVar(&ConvertDeploymentConfig, "deployment-config", true, "Generate an OpenShift deploymentconfig object")
	convertCmd.Flags().BoolVar(&ConvertInsecureRepo, "insecure-repository", false, "Use an insecure Docker repository for OpenShift ImageStream")
	convertCmd.Flags().StringVar(&ConvertBuildRepo, "build-repo", "", "Specify source repository for buildconfig (default remote origin)")
	convertCmd.Flags().StringVar(&ConvertBuildBranch, "build-branch", "", "Specify repository branch to use for buildconfig (default master)")
	convertCmd.Flags().MarkDeprecated("deployment-config", "use --controller")
	convertCmd.Flags().MarkHidden("deployment-config")
	convertCmd.Flags().MarkHidden("insecure-repository")
	convertCmd.Flags().MarkHidden("build-repo")
	convertCmd.Flags().MarkHidden("build-branch")

	// Standard between the two
	convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config"(OpenShift only)|"none")`)
	convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format")
	convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.")
	convertCmd.Flags().MarkShorthandDeprecated("y", "YAML is the default format now.")
	convertCmd.Flags().BoolVarP(&ConvertJSON, "json", "j", false, "Generate resource files into JSON format")
	convertCmd.Flags().BoolVar(&ConvertStdout, "stdout", false, "Print converted objects to stdout")
	convertCmd.Flags().StringVarP(&ConvertOut, "out", "o", "", "Specify a file name or directory to save objects to (if path does not exist, a file will be created)")
	convertCmd.Flags().IntVar(&ConvertReplicas, "replicas", 1, "Specify the number of replicas in the generated resource spec")
	convertCmd.Flags().StringVar(&ConvertVolumes, "volumes", "persistentVolumeClaim", `Volumes to be generated ("persistentVolumeClaim"|"emptyDir"|"hostPath" | "configMap")`)

	// Deprecated commands
	convertCmd.Flags().BoolVar(&ConvertEmptyVols, "emptyvols", false, "Use Empty Volumes. Do not generate PVCs")
	convertCmd.Flags().MarkDeprecated("emptyvols", "emptyvols has been marked as deprecated. Use --volumes empty")

	convertCmd.Flags().IntVar(&ConvertYAMLIndent, "indent", 2, "Spaces length to indent generated yaml files")

	// In order to 'separate' both OpenShift and Kubernetes only flags. A custom help page is created
	customHelp := `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Kubernetes Flags:
      --daemon-set               Generate a Kubernetes daemonset object (deprecated, use --controller instead)
  -d, --deployment               Generate a Kubernetes deployment object (deprecated, use --controller instead)
  -c, --chart                    Create a Helm chart for converted objects
      --replication-controller   Generate a Kubernetes replication controller object (deprecated, use --controller instead)

OpenShift Flags:
      --build-branch             Specify repository branch to use for buildconfig (default is current branch name)
      --build-repo               Specify source repository for buildconfig (default is current branch's remote url)
      --deployment-config        Generate an OpenShift deployment config object
      --insecure-repository      Specify to use insecure docker repository while generating Openshift image stream object

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}

Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
	// Set the help template + add the command to root
	convertCmd.SetUsageTemplate(customHelp)

	RootCmd.AddCommand(convertCmd)
}
<commit_msg>Add support for push-image with --build local (#1257)<commit_after>/*
Copyright 2017 The Kubernetes Authors All rights reserved.

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 cmd

import (
	"strings"

	"github.com/kubernetes/kompose/pkg/app"
	"github.com/kubernetes/kompose/pkg/kobject"
	log "github.com/sirupsen/logrus"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

// TODO: comment
var (
	ConvertOut                   string
	ConvertBuildRepo             string
	ConvertBuildBranch           string
	ConvertBuild                 string
	ConvertVolumes               string
	ConvertChart                 bool
	ConvertDeployment            bool
	ConvertDaemonSet             bool
	ConvertReplicationController bool
	ConvertYaml                  bool
	ConvertJSON                  bool
	ConvertStdout                bool
	ConvertEmptyVols             bool
	ConvertInsecureRepo          bool
	ConvertDeploymentConfig      bool
	ConvertReplicas              int
	ConvertController            string
	ConvertPushImage             bool
	ConvertOpt                   kobject.ConvertOptions
	ConvertYAMLIndent            int
)

var convertCmd = &cobra.Command{
	Use:   "convert [file]",
	Short: "Convert a Docker Compose file",
	PreRun: func(cmd *cobra.Command, args []string) {

		// Check that build-config wasn't passed in with --provider=kubernetes
		if GlobalProvider == "kubernetes" && UpBuild == "build-config" {
			log.Fatalf("build-config is not a valid --build parameter with provider Kubernetes")
		}

		// Create the Convert Options.
		ConvertOpt = kobject.ConvertOptions{
			ToStdout:                    ConvertStdout,
			CreateChart:                 ConvertChart,
			GenerateYaml:                ConvertYaml,
			GenerateJSON:                ConvertJSON,
			Replicas:                    ConvertReplicas,
			InputFiles:                  GlobalFiles,
			OutFile:                     ConvertOut,
			Provider:                    GlobalProvider,
			CreateD:                     ConvertDeployment,
			CreateDS:                    ConvertDaemonSet,
			CreateRC:                    ConvertReplicationController,
			Build:                       ConvertBuild,
			BuildRepo:                   ConvertBuildRepo,
			BuildBranch:                 ConvertBuildBranch,
			PushImage:                   ConvertPushImage,
			CreateDeploymentConfig:      ConvertDeploymentConfig,
			EmptyVols:                   ConvertEmptyVols,
			Volumes:                     ConvertVolumes,
			InsecureRepository:          ConvertInsecureRepo,
			IsDeploymentFlag:            cmd.Flags().Lookup("deployment").Changed,
			IsDaemonSetFlag:             cmd.Flags().Lookup("daemon-set").Changed,
			IsReplicationControllerFlag: cmd.Flags().Lookup("replication-controller").Changed,
			Controller:                  strings.ToLower(ConvertController),
			IsReplicaSetFlag:            cmd.Flags().Lookup("replicas").Changed,
			IsDeploymentConfigFlag:      cmd.Flags().Lookup("deployment-config").Changed,
			YAMLIndent:                  ConvertYAMLIndent,
		}

		// Validate before doing anything else. Use "bundle" if passed in.
		app.ValidateFlags(GlobalBundle, args, cmd, &ConvertOpt)
		app.ValidateComposeFile(&ConvertOpt)
	},
	Run: func(cmd *cobra.Command, args []string) {

		app.Convert(ConvertOpt)
	},
}

func init() {

	// Automatically grab environment variables
	viper.AutomaticEnv()

	// Kubernetes only
	convertCmd.Flags().BoolVarP(&ConvertChart, "chart", "c", false, "Create a Helm chart for converted objects")
	convertCmd.Flags().BoolVar(&ConvertDaemonSet, "daemon-set", false, "Generate a Kubernetes daemonset object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVarP(&ConvertDeployment, "deployment", "d", false, "Generate a Kubernetes deployment object (deprecated, use --controller instead)")
	convertCmd.Flags().BoolVar(&ConvertReplicationController, "replication-controller", false, "Generate a Kubernetes replication controller object (deprecated, use --controller instead)")
	convertCmd.Flags().StringVar(&ConvertController, "controller", "", `Set the output controller ("deployment"|"daemonSet"|"replicationController")`)
	convertCmd.Flags().MarkDeprecated("daemon-set", "use --controller")
	convertCmd.Flags().MarkDeprecated("deployment", "use --controller")
	convertCmd.Flags().MarkDeprecated("replication-controller", "use --controller")
	convertCmd.Flags().MarkHidden("chart")
	convertCmd.Flags().MarkHidden("daemon-set")
	convertCmd.Flags().MarkHidden("replication-controller")
	convertCmd.Flags().MarkHidden("deployment")

	// OpenShift only
	convertCmd.Flags().BoolVar(&ConvertDeploymentConfig, "deployment-config", true, "Generate an OpenShift deploymentconfig object")
	convertCmd.Flags().BoolVar(&ConvertInsecureRepo, "insecure-repository", false, "Use an insecure Docker repository for OpenShift ImageStream")
	convertCmd.Flags().StringVar(&ConvertBuildRepo, "build-repo", "", "Specify source repository for buildconfig (default remote origin)")
	convertCmd.Flags().StringVar(&ConvertBuildBranch, "build-branch", "", "Specify repository branch to use for buildconfig (default master)")
	convertCmd.Flags().MarkDeprecated("deployment-config", "use --controller")
	convertCmd.Flags().MarkHidden("deployment-config")
	convertCmd.Flags().MarkHidden("insecure-repository")
	convertCmd.Flags().MarkHidden("build-repo")
	convertCmd.Flags().MarkHidden("build-branch")

	// Standard between the two
	convertCmd.Flags().StringVar(&ConvertBuild, "build", "none", `Set the type of build ("local"|"build-config"(OpenShift only)|"none")`)
	convertCmd.Flags().BoolVar(&ConvertPushImage, "push-image", true, "If we should push the docker image we built")
	convertCmd.Flags().BoolVarP(&ConvertYaml, "yaml", "y", false, "Generate resource files into YAML format")
	convertCmd.Flags().MarkDeprecated("yaml", "YAML is the default format now.")
	convertCmd.Flags().MarkShorthandDeprecated("y", "YAML is the default format now.")
	convertCmd.Flags().BoolVarP(&ConvertJSON, "json", "j", false, "Generate resource files into JSON format")
	convertCmd.Flags().BoolVar(&ConvertStdout, "stdout", false, "Print converted objects to stdout")
	convertCmd.Flags().StringVarP(&ConvertOut, "out", "o", "", "Specify a file name or directory to save objects to (if path does not exist, a file will be created)")
	convertCmd.Flags().IntVar(&ConvertReplicas, "replicas", 1, "Specify the number of replicas in the generated resource spec")
	convertCmd.Flags().StringVar(&ConvertVolumes, "volumes", "persistentVolumeClaim", `Volumes to be generated ("persistentVolumeClaim"|"emptyDir"|"hostPath" | "configMap")`)

	// Deprecated commands
	convertCmd.Flags().BoolVar(&ConvertEmptyVols, "emptyvols", false, "Use Empty Volumes. Do not generate PVCs")
	convertCmd.Flags().MarkDeprecated("emptyvols", "emptyvols has been marked as deprecated. Use --volumes empty")

	convertCmd.Flags().IntVar(&ConvertYAMLIndent, "indent", 2, "Spaces length to indent generated yaml files")

	// In order to 'separate' both OpenShift and Kubernetes only flags. A custom help page is created
	customHelp := `Usage:{{if .Runnable}}
  {{if .HasAvailableFlags}}{{appendIfNotPresent .UseLine "[flags]"}}{{else}}{{.UseLine}}{{end}}{{end}}{{if .HasAvailableSubCommands}}
  {{ .CommandPath}} [command]{{end}}{{if gt .Aliases 0}}

Aliases:
  {{.NameAndAliases}}
{{end}}{{if .HasExample}}

Examples:
{{ .Example }}{{end}}{{ if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if .IsAvailableCommand}}
  {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableLocalFlags}}

Kubernetes Flags:
      --daemon-set               Generate a Kubernetes daemonset object (deprecated, use --controller instead)
  -d, --deployment               Generate a Kubernetes deployment object (deprecated, use --controller instead)
  -c, --chart                    Create a Helm chart for converted objects
      --replication-controller   Generate a Kubernetes replication controller object (deprecated, use --controller instead)

OpenShift Flags:
      --build-branch             Specify repository branch to use for buildconfig (default is current branch name)
      --build-repo               Specify source repository for buildconfig (default is current branch's remote url)
      --deployment-config        Generate an OpenShift deployment config object
      --insecure-repository      Specify to use insecure docker repository while generating Openshift image stream object

Flags:
{{.LocalFlags.FlagUsages | trimRightSpace}}{{end}}{{ if .HasAvailableInheritedFlags}}

Global Flags:
{{.InheritedFlags.FlagUsages | trimRightSpace}}{{end}}{{if .HasHelpSubCommands}}

Additional help topics:{{range .Commands}}{{if .IsHelpCommand}}
  {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{ if .HasAvailableSubCommands }}
Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}}
`
	// Set the help template + add the command to root
	convertCmd.SetUsageTemplate(customHelp)

	RootCmd.AddCommand(convertCmd)
}
<|endoftext|>


<commit_before>package main

import (
	"context"
	"errors"
	"fmt"
	"log"

	"github.com/anacrolix/dht/v2"
	"github.com/anacrolix/dht/v2/exts/getput"
	"github.com/anacrolix/dht/v2/krpc"
)

type GetCmd struct {
	Target []krpc.ID `arg:"positional"`
	Seq    *int64
	Salt   string
}

func get(cmd *GetCmd) (err error) {
	s, err := dht.NewServer(nil)
	if err != nil {
		return
	}
	defer s.Close()
	if len(cmd.Target) == 0 {
		return errors.New("no targets specified")
	}
	for _, t := range cmd.Target {
		log.Printf("getting %v", t)
		var v interface{}
		v, _, err = getput.Get(context.Background(), t, s, cmd.Seq, []byte(cmd.Salt))
		if err != nil {
			log.Printf("error getting %v: %v", t, err)
		} else {
			fmt.Println(v)
		}
	}
	return nil
}
<commit_msg>Improve get output<commit_after>package main

import (
	"context"
	"errors"
	"log"
	"os"

	"github.com/anacrolix/dht/v2"
	"github.com/anacrolix/dht/v2/exts/getput"
	"github.com/anacrolix/dht/v2/krpc"
	"github.com/anacrolix/torrent/bencode"
)

type GetCmd struct {
	Target []krpc.ID `arg:"positional"`
	Seq    *int64
	Salt   string
}

func get(cmd *GetCmd) (err error) {
	s, err := dht.NewServer(nil)
	if err != nil {
		return
	}
	defer s.Close()
	if len(cmd.Target) == 0 {
		return errors.New("no targets specified")
	}
	for _, t := range cmd.Target {
		log.Printf("getting %v", t)
		v, _, err := getput.Get(context.Background(), t, s, cmd.Seq, []byte(cmd.Salt))
		if err != nil {
			log.Printf("error getting %v: %v", t, err)
		} else {
			log.Printf("got result [seq=%v, mutable=%v]", v.Seq, v.Mutable)
			os.Stdout.Write(bencode.MustMarshal(v.V))
			os.Stdout.WriteString("\n")
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/funkygao/gafka"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gocli"
	"github.com/funkygao/log4go"
)

func main() {
	ctx.LoadConfig("/etc/gafka.cf")
	setupLogging()

	app := os.Args[0]
	args := os.Args[1:]
	for _, arg := range args {
		if arg == "-v" || arg == "--version" {
			newArgs := make([]string, len(args)+1)
			newArgs[0] = "version"
			copy(newArgs[1:], args)
			args = newArgs
			break
		}

		if arg == "--generate-bash-completion" {
			for name, _ := range commands {
				fmt.Println(name)
			}
			return
		}
	}
	c := cli.NewCLI(app, gafka.Version+"-"+gafka.BuildId)
	c.Args = os.Args[1:]
	c.Commands = commands
	c.HelpFunc = cli.BasicHelpFunc(app)

	exitCode, err := c.Run()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%+v\n", err)
		os.Exit(1)
	}

	os.Exit(exitCode)
}

func setupLogging() {
	log.SetOutput(ioutil.Discard)

	level := log4go.DEBUG
	switch ctx.LogLevel() {
	case "info":
		level = log4go.INFO

	case "warn":
		level = log4go.WARNING

	case "error":
		level = log4go.ERROR

	case "debug":
		level = log4go.DEBUG

	case "trace":
		level = log4go.TRACE

	case "alarm":
		level = log4go.ALARM
	}

	for _, filter := range log4go.Global {
		filter.Level = level
	}

	log4go.AddFilter("stdout", level, log4go.NewConsoleLogWriter())
}
<commit_msg>if show version, exit status should still be 0<commit_after>package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"

	"github.com/funkygao/gafka"
	"github.com/funkygao/gafka/ctx"
	"github.com/funkygao/gocli"
	"github.com/funkygao/log4go"
)

func main() {
	ctx.LoadConfig("/etc/gafka.cf")
	setupLogging()

	app := os.Args[0]
	args := os.Args[1:]
	for _, arg := range args {
		if arg == "-v" || arg == "--version" {
			newArgs := make([]string, len(args)+1)
			newArgs[0] = "version"
			copy(newArgs[1:], args)
			args = newArgs
			break
		}

		if arg == "--generate-bash-completion" {
			for name, _ := range commands {
				fmt.Println(name)
			}
			return
		}
	}
	c := cli.NewCLI(app, gafka.Version+"-"+gafka.BuildId)
	c.Args = os.Args[1:]
	c.Commands = commands
	c.HelpFunc = cli.BasicHelpFunc(app)

	exitCode, err := c.Run()
	if err != nil {
		fmt.Fprintf(os.Stderr, "%+v\n", err)
		os.Exit(1)
	} else if c.IsVersion() {
		os.Exit(0)
	}

	os.Exit(exitCode)
}

func setupLogging() {
	log.SetOutput(ioutil.Discard)

	level := log4go.DEBUG
	switch ctx.LogLevel() {
	case "info":
		level = log4go.INFO

	case "warn":
		level = log4go.WARNING

	case "error":
		level = log4go.ERROR

	case "debug":
		level = log4go.DEBUG

	case "trace":
		level = log4go.TRACE

	case "alarm":
		level = log4go.ALARM
	}

	for _, filter := range log4go.Global {
		filter.Level = level
	}

	log4go.AddFilter("stdout", level, log4go.NewConsoleLogWriter())
}
<|endoftext|>


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

// ht generates HTTP requests and checks the received responses.
//
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/vdobler/ht/ht"
	"github.com/vdobler/ht/internal/hjson"
	"github.com/vdobler/ht/populate"
	"github.com/vdobler/ht/suite"

	_ "github.com/go-sql-driver/mysql"
)

// A Command is one of the subcommands of ht.
type Command struct {
	// One of RunSuites, RunTest and RunArgs must be provided by the command.
	RunSuites func(cmd *Command, suites []*suite.RawSuite)
	RunTests  func(cmd *Command, tests []*suite.RawTest)
	RunArgs   func(cmd *Command, tests []string)

	Usage       string        // must start with command name
	Description string        // short description for 'ht help'
	Help        string        // the output of 'ht help <cmd>'
	Flag        *flag.FlagSet // the flags for this command
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) usage() {
	eol := strings.Index(c.Help, "\n")
	fmt.Fprintf(os.Stderr, "%s\n\n", c.Help[:eol])
	fmt.Fprintf(os.Stderr, "Usage:\n\n")
	fmt.Fprintf(os.Stderr, "    ht %s\n", c.Usage)
	fmt.Fprintf(os.Stderr, "%s\n", c.Help[eol+1:])
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands []*Command

func init() {
	commands = []*Command{
		cmdVersion,
		cmdHelp,
		cmdDoc,
		cmdRecord,
		cmdList,
		cmdQuick,
		cmdRun,
		cmdExec,
		// cmdBench,
		// cmdMonitor,
		cmdFingerprint,
		cmdReconstruct,
		cmdLoad,
		cmdStat,
		cmdMock,
		cmdGUI,
	}
}

// usage prints usage information.
func usage() {
	formatedCmdList := ""

	for _, cmd := range commands {
		formatedCmdList += fmt.Sprintf("    %-12s %s\n",
			cmd.Name(), cmd.Description)
	}

	fmt.Printf(`ht is a tool to generate HTTP request and test the response.

Usage:

    ht <command> [flags...] <args depending on command>...

The commands are:
%s
Run 'ht help <command>' to display the usage of <command> and
run 'ht help help' to see what other help you can get.
`, formatedCmdList)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		usage()
		os.Exit(9)
	}

	for _, cmd := range commands {
		if cmd.Name() != args[0] {
			continue
		}

		cmd.Flag.Usage = func() { cmd.usage() }
		err := cmd.Flag.Parse(args[1:])
		if err != nil {
			if err == flag.ErrHelp {
				cmd.Flag.PrintDefaults()
				os.Exit(0)
			}
			os.Exit(9)
		}
		fillVariablesFlagFrom(variablesFile)
		args = cmd.Flag.Args()
		switch {
		case cmd.RunSuites != nil:
			suites := loadSuites(args)
			cmd.RunSuites(cmd, suites)
		case cmd.RunTests != nil:
			tests := loadTests(args)
			cmd.RunTests(cmd, tests)
		default:
			cmd.RunArgs(cmd, args)
		}
		return
	}

	fmt.Fprintf(os.Stderr, "ht: unknown subcommand %q\nRun 'ht help' for usage.\n",
		args[0])
	os.Exit(9)
}

// For any entry in args of the form <dirname>/... look for any *.suite file
// below <dirname> and expand the arglist.
func expandTrippleDots(args []string) []string {
	expanded := []string{}

	// walking the directory, capturing all *.suite falls while swallowing
	// all errors.
	walk := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && len(info.Name()) > 6 && strings.HasSuffix(path, ".suite") {
			expanded = append(expanded, path)
		}
		return nil
	}

	for _, arg := range args {
		if !strings.HasSuffix(arg, "/...") {
			expanded = append(expanded, arg)
			continue
		}
		arg := arg[:len(arg)-4] // strip /...
		finfo, err := os.Stat(arg)
		if err != nil || !finfo.IsDir() {
			// Not a directory? Don't process and fail later.
			expanded = append(expanded, arg)
			continue
		}
		filepath.Walk(arg, walk)
	}
	return expanded
}

func loadSuites(args []string) []*suite.RawSuite {
	args = expandTrippleDots(args)

	var suites []*suite.RawSuite

	// Handle -only and -skip flags.
	only, skip := splitTestIDs(onlyFlag), splitTestIDs(skipFlag)

	// Input and setup suites from command line arguments.
	exit := false
	for _, arg := range args {
		// Process arguments of the form <name>@<archive>.
		var fs suite.FileSystem
		if i := strings.Index(arg, "@"); i != -1 {
			blob, err := ioutil.ReadFile(arg[i+1:])
			if err != nil {
				fmt.Fprintf(os.Stderr, "Cannot load %q: %s\n", arg[i+1:], err)
				os.Exit(9)
			}
			fs, err = suite.NewFileSystem(string(blob))
			if err != nil {
				fmt.Fprintf(os.Stderr, "Cannot load %q: %s\n", arg[i+1:], err)
				os.Exit(9)
			}
			arg = arg[:i]
		}
		s, err := suite.LoadRawSuite(arg, fs)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Cannot read suite %q: %s\n", arg, err)
			exit = true
			continue
		}
		// for varName, varVal := range variablesFlag {
		// 	suite.Variables[varName] = varVal
		// }
		err = s.Validate(variablesFlag)
		if err != nil {
			if el, ok := err.(ht.ErrorList); ok {
				for _, msg := range el.AsStrings() {
					fmt.Fprintln(os.Stderr, msg)
				}
			} else {
				fmt.Fprintln(os.Stderr, err.Error())
			}
			exit = true
		}
		// setVerbosity(s)
		suites = append(suites, s)
	}
	if exit {
		os.Exit(8)
	}

	// Merge only into skip.
	if len(only) > 0 {
		for sNo := range suites {
			for tNo := range suites[sNo].RawTests() {
				id := fmt.Sprintf("%d.%d", sNo+1, tNo+1)
				if !only[id] {
					skip[id] = true
				}
			}
		}
	}

	// Disable tests based on the -only and -skip flags.
	for sNo := range suites {
		for tNo, rt := range suites[sNo].RawTests() {
			id := fmt.Sprintf("%d.%d", sNo+1, tNo+1)
			if skip[id] {
				rt.Disable()
				fmt.Printf("Skipping test %s %q\n", id, rt.Name)
			}
		}
	}

	// Propagate verbosity from command line to suite/test.
	for _, s := range suites {
		setVerbosity(s)
	}

	return suites
}

func splitTestIDs(f string) map[string]bool {
	ids := make(map[string]bool)
	if len(f) == 0 {
		return ids
	}
	fp := strings.Split(f, ",")
	for _, x := range fp {
		xp := strings.SplitN(x, ".", 2)
		s, t := "1", xp[0]
		if len(xp) == 2 {
			s, t = xp[0], xp[1]
		}
		sNo := mustAtoi(s)
		beg, end := 1, 99
		if i := strings.Index(t, "-"); i > -1 {
			if i > 0 {
				beg = mustAtoi(t[:i])
			}
			if i < len(t)-1 {
				end = mustAtoi(t[i+1:])
			}
		} else {
			beg = mustAtoi(t)
			end = beg
		}
		for tNo := beg; tNo <= end; tNo++ {
			id := fmt.Sprintf("%d.%d", sNo, tNo)
			ids[id] = true
		}
	}
	return ids
}

func mustAtoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err.Error())
		os.Exit(9)
	}
	return n
}

// set (-verbosity) or increase (-v ... -vvvv) test verbosities of s.
func setVerbosity(rs *suite.RawSuite) {
	if verbosity != -99 {
		rs.Verbosity = verbosity
	} else if vvvv {
		rs.Verbosity += 4
	} else if vvv {
		rs.Verbosity += 3
	} else if vv {
		rs.Verbosity += 2
	} else if v {
		rs.Verbosity += 1
	}
}

// loadTests loads single Tests and combines them into an artificial
// Suite, ready for execution. Unrolling happens, but only the first
// unrolled test gets included into the suite.
func loadTests(args []string) []*suite.RawTest {
	tt := []*suite.RawTest{}
	// Input and setup tests from command line arguments.
	for _, arg := range args {
		test, err := suite.LoadRawTest(arg, nil)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Cannot read test %q: %s\n", arg, err)
			os.Exit(8)
		}
		tt = append(tt, test)
	}

	return tt
}

// fillVariablesFlagFrom reads in the file variablesFile and sets the
// jet unset variables. This means that the resulting variable/values in
// variablesFlag looks like the variablesFile was loaded first and the
// -D flags overwrite the ones loaded from file.
func fillVariablesFlagFrom(variablesFile string) {
	if variablesFile == "" {
		return
	}
	data, err := ioutil.ReadFile(variablesFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot read variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}
	v := map[string]interface{}{}
	err = hjson.Unmarshal(data, &v)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot unmarshal variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}
	vv := map[string]string{}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Malformed variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}

	err = populate.Strict(&vv, v)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Malformed variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}

	for n, k := range vv {
		if _, ok := variablesFlag[n]; !ok {
			variablesFlag[n] = k
		}
	}
}
<commit_msg>cmd/ht: allow archive files also for tests<commit_after>// Copyright 2014 Volker Dobler.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// ht generates HTTP requests and checks the received responses.
//
package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/vdobler/ht/ht"
	"github.com/vdobler/ht/internal/hjson"
	"github.com/vdobler/ht/populate"
	"github.com/vdobler/ht/suite"

	_ "github.com/go-sql-driver/mysql"
)

// A Command is one of the subcommands of ht.
type Command struct {
	// One of RunSuites, RunTest and RunArgs must be provided by the command.
	RunSuites func(cmd *Command, suites []*suite.RawSuite)
	RunTests  func(cmd *Command, tests []*suite.RawTest)
	RunArgs   func(cmd *Command, tests []string)

	Usage       string        // must start with command name
	Description string        // short description for 'ht help'
	Help        string        // the output of 'ht help <cmd>'
	Flag        *flag.FlagSet // the flags for this command
}

// Name returns the command's name: the first word in the usage line.
func (c *Command) Name() string {
	name := c.Usage
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

func (c *Command) usage() {
	eol := strings.Index(c.Help, "\n")
	fmt.Fprintf(os.Stderr, "%s\n\n", c.Help[:eol])
	fmt.Fprintf(os.Stderr, "Usage:\n\n")
	fmt.Fprintf(os.Stderr, "    ht %s\n", c.Usage)
	fmt.Fprintf(os.Stderr, "%s\n", c.Help[eol+1:])
}

// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
var commands []*Command

func init() {
	commands = []*Command{
		cmdVersion,
		cmdHelp,
		cmdDoc,
		cmdRecord,
		cmdList,
		cmdQuick,
		cmdRun,
		cmdExec,
		// cmdBench,
		// cmdMonitor,
		cmdFingerprint,
		cmdReconstruct,
		cmdLoad,
		cmdStat,
		cmdMock,
		cmdGUI,
	}
}

// usage prints usage information.
func usage() {
	formatedCmdList := ""

	for _, cmd := range commands {
		formatedCmdList += fmt.Sprintf("    %-12s %s\n",
			cmd.Name(), cmd.Description)
	}

	fmt.Printf(`ht is a tool to generate HTTP request and test the response.

Usage:

    ht <command> [flags...] <args depending on command>...

The commands are:
%s
Run 'ht help <command>' to display the usage of <command> and
run 'ht help help' to see what other help you can get.
`, formatedCmdList)
}

func main() {
	flag.Usage = usage
	flag.Parse()

	args := flag.Args()
	if len(args) < 1 {
		usage()
		os.Exit(9)
	}

	for _, cmd := range commands {
		if cmd.Name() != args[0] {
			continue
		}

		cmd.Flag.Usage = func() { cmd.usage() }
		err := cmd.Flag.Parse(args[1:])
		if err != nil {
			if err == flag.ErrHelp {
				cmd.Flag.PrintDefaults()
				os.Exit(0)
			}
			os.Exit(9)
		}
		fillVariablesFlagFrom(variablesFile)
		args = cmd.Flag.Args()
		switch {
		case cmd.RunSuites != nil:
			suites := loadSuites(args)
			cmd.RunSuites(cmd, suites)
		case cmd.RunTests != nil:
			tests := loadTests(args)
			cmd.RunTests(cmd, tests)
		default:
			cmd.RunArgs(cmd, args)
		}
		return
	}

	fmt.Fprintf(os.Stderr, "ht: unknown subcommand %q\nRun 'ht help' for usage.\n",
		args[0])
	os.Exit(9)
}

// For any entry in args of the form <dirname>/... look for any *.suite file
// below <dirname> and expand the arglist.
func expandTrippleDots(args []string) []string {
	expanded := []string{}

	// walking the directory, capturing all *.suite falls while swallowing
	// all errors.
	walk := func(path string, info os.FileInfo, err error) error {
		if !info.IsDir() && len(info.Name()) > 6 && strings.HasSuffix(path, ".suite") {
			expanded = append(expanded, path)
		}
		return nil
	}

	for _, arg := range args {
		if !strings.HasSuffix(arg, "/...") {
			expanded = append(expanded, arg)
			continue
		}
		arg := arg[:len(arg)-4] // strip /...
		finfo, err := os.Stat(arg)
		if err != nil || !finfo.IsDir() {
			// Not a directory? Don't process and fail later.
			expanded = append(expanded, arg)
			continue
		}
		filepath.Walk(arg, walk)
	}
	return expanded
}

func filesystemFor(arg string) (suite.FileSystem, string) {
	i := strings.Index(arg, "@")
	if i == -1 {
		return nil, arg // Not an archive, use real file system from OS.
	}

	blob, err := ioutil.ReadFile(arg[i+1:])
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot load %q: %s\n", arg[i+1:], err)
		os.Exit(9)
	}
	fs, err := suite.NewFileSystem(string(blob))
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot load %q: %s\n", arg[i+1:], err)
		os.Exit(9)
	}
	arg = arg[:i]
	return fs, arg
}

func loadSuites(args []string) []*suite.RawSuite {
	args = expandTrippleDots(args)

	var suites []*suite.RawSuite

	// Handle -only and -skip flags.
	only, skip := splitTestIDs(onlyFlag), splitTestIDs(skipFlag)

	// Input and setup suites from command line arguments.
	exit := false
	for _, arg := range args {
		// Process arguments of the form <name>@<archive>.
		fs, arg := filesystemFor(arg)
		s, err := suite.LoadRawSuite(arg, fs)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Cannot read suite %q: %s\n", arg, err)
			exit = true
			continue
		}
		// for varName, varVal := range variablesFlag {
		// 	suite.Variables[varName] = varVal
		// }
		err = s.Validate(variablesFlag)
		if err != nil {
			if el, ok := err.(ht.ErrorList); ok {
				for _, msg := range el.AsStrings() {
					fmt.Fprintln(os.Stderr, msg)
				}
			} else {
				fmt.Fprintln(os.Stderr, err.Error())
			}
			exit = true
		}
		// setVerbosity(s)
		suites = append(suites, s)
	}
	if exit {
		os.Exit(8)
	}

	// Merge only into skip.
	if len(only) > 0 {
		for sNo := range suites {
			for tNo := range suites[sNo].RawTests() {
				id := fmt.Sprintf("%d.%d", sNo+1, tNo+1)
				if !only[id] {
					skip[id] = true
				}
			}
		}
	}

	// Disable tests based on the -only and -skip flags.
	for sNo := range suites {
		for tNo, rt := range suites[sNo].RawTests() {
			id := fmt.Sprintf("%d.%d", sNo+1, tNo+1)
			if skip[id] {
				rt.Disable()
				fmt.Printf("Skipping test %s %q\n", id, rt.Name)
			}
		}
	}

	// Propagate verbosity from command line to suite/test.
	for _, s := range suites {
		setVerbosity(s)
	}

	return suites
}

func splitTestIDs(f string) map[string]bool {
	ids := make(map[string]bool)
	if len(f) == 0 {
		return ids
	}
	fp := strings.Split(f, ",")
	for _, x := range fp {
		xp := strings.SplitN(x, ".", 2)
		s, t := "1", xp[0]
		if len(xp) == 2 {
			s, t = xp[0], xp[1]
		}
		sNo := mustAtoi(s)
		beg, end := 1, 99
		if i := strings.Index(t, "-"); i > -1 {
			if i > 0 {
				beg = mustAtoi(t[:i])
			}
			if i < len(t)-1 {
				end = mustAtoi(t[i+1:])
			}
		} else {
			beg = mustAtoi(t)
			end = beg
		}
		for tNo := beg; tNo <= end; tNo++ {
			id := fmt.Sprintf("%d.%d", sNo, tNo)
			ids[id] = true
		}
	}
	return ids
}

func mustAtoi(s string) int {
	n, err := strconv.Atoi(s)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s", err.Error())
		os.Exit(9)
	}
	return n
}

// set (-verbosity) or increase (-v ... -vvvv) test verbosities of s.
func setVerbosity(rs *suite.RawSuite) {
	if verbosity != -99 {
		rs.Verbosity = verbosity
	} else if vvvv {
		rs.Verbosity += 4
	} else if vvv {
		rs.Verbosity += 3
	} else if vv {
		rs.Verbosity += 2
	} else if v {
		rs.Verbosity += 1
	}
}

// loadTests loads single Tests and combines them into an artificial
// Suite, ready for execution. Unrolling happens, but only the first
// unrolled test gets included into the suite.
func loadTests(args []string) []*suite.RawTest {
	tt := []*suite.RawTest{}
	// Input and setup tests from command line arguments.
	for _, arg := range args {
		fs, arg := filesystemFor(arg)
		test, err := suite.LoadRawTest(arg, fs)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Cannot read test %q: %s\n", arg, err)
			os.Exit(8)
		}
		tt = append(tt, test)
	}

	return tt
}

// fillVariablesFlagFrom reads in the file variablesFile and sets the
// jet unset variables. This means that the resulting variable/values in
// variablesFlag looks like the variablesFile was loaded first and the
// -D flags overwrite the ones loaded from file.
func fillVariablesFlagFrom(variablesFile string) {
	if variablesFile == "" {
		return
	}
	data, err := ioutil.ReadFile(variablesFile)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot read variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}
	v := map[string]interface{}{}
	err = hjson.Unmarshal(data, &v)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Cannot unmarshal variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}
	vv := map[string]string{}
	if err != nil {
		fmt.Fprintf(os.Stderr, "Malformed variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}

	err = populate.Strict(&vv, v)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Malformed variable file %q: %s\n", variablesFile, err)
		os.Exit(8)
	}

	for n, k := range vv {
		if _, ok := variablesFlag[n]; !ok {
			variablesFlag[n] = k
		}
	}
}
<|endoftext|>


<commit_before>package cmd

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
)

// migrateCmd represents the migrate command
var migrateCmd = &cobra.Command{
	Use:   "migrate [shipment] [environment]",
	Short: "Migrate a shipment environment to another platform",
	Long: `Migrate a shipment environment to another platform

The migrate command outputs files that are useful for migrating a shipment/environment to another platform.
Note that the migrate command only outputs files and does not perform an actual migration.

The migrate command's --build-provider flag allows you to generate build provider-specific files that allow you to build Docker images and do CI/CD.
`,
	Example: fmt.Sprintf(`harbor-compose migrate my-shipment dev
harbor-compose migrate my-shipment dev --platform ecsfargate --build-provider circleciv2
harbor-compose migrate my-shipment prod --platform ecsfargate
harbor-compose migrate my-shipment prod --platform ecsfargate --role admin
harbor-compose migrate my-shipment prod --template-tag %s
harbor-compose migrate my-shipment prod --app my-fargate-app

# migrate to the specified account
harbor-compose migrate my-shipment prod \
	--account-name my-aws-account \
	--account-id 123456789012 \
	--vpc vpc-123 \
	--private-subnets subnet-123,subnet-456 \
	--public-subnets subnet-789,subnet-012
`, latestTemplateVersion),
	Run:    migrate,
	PreRun: preRunHook,
}

const (
	latestTemplateVersion = "v0.2.0"
)

var migrateBuildProvider string
var migratePlatform string
var migrateRole string
var migrateTemplateTag string
var migrateProfile string
var migrateAccountID string
var migrateAccountName string
var migrateVPC string
var migratePrivateSubnets string
var migratePublicSubnets string
var migrateAppName string

func init() {
	migrateCmd.PersistentFlags().StringVarP(&migratePlatform, "platform", "p", "ecsfargate", "target migration platform")
	migrateCmd.PersistentFlags().StringVarP(&migrateBuildProvider, "build-provider", "b", "", "migrate build provider-specific files that allow you to build Docker images do CI/CD")
	migrateCmd.PersistentFlags().StringVarP(&migrateTemplateTag, "template-tag", "t", latestTemplateVersion, "migrate using specified template")
	migrateCmd.PersistentFlags().StringVarP(&migrateRole, "role", "r", "devops", "migrate using specified aws role")
	migrateCmd.PersistentFlags().StringVar(&migrateProfile, "profile", "", "migrate using specified aws profile")

	migrateCmd.PersistentFlags().StringVarP(&migrateAccountName, "account-name", "n", "", "migrate to the specified Account Name")
	migrateCmd.PersistentFlags().StringVarP(&migrateAccountID, "account-id", "i", "", "migrate to the specified Account ID")
	migrateCmd.PersistentFlags().StringVar(&migrateVPC, "vpc", "", "migrate to the specified VPC ID")
	migrateCmd.PersistentFlags().StringVar(&migratePrivateSubnets, "private-subnets", "", "migrate using the specified private subnets (comma-delimited)")
	migrateCmd.PersistentFlags().StringVar(&migratePublicSubnets, "public-subnets", "", "migrate using the specified public subnets (comma-delimited)")

	migrateCmd.PersistentFlags().StringVarP(&migrateAppName, "app", "a", "", "use this app name instead of shipment name")

	RootCmd.AddCommand(migrateCmd)
}

func migrate(cmd *cobra.Command, args []string) {
	if len(args) < 2 {
		cmd.Help()
		os.Exit(-1)
	}

	//if account-name is specified, then a number of other args are required
	if migrateAccountName != "" {
		if migrateAccountID == "" {
			fmt.Println("--account-id is required if using --account-name")
			os.Exit(-1)
		}
		if migrateVPC == "" {
			fmt.Println("--vpc is required if using --account-name")
			os.Exit(-1)
		}
		if migratePrivateSubnets == "" {
			fmt.Println("--private-subnets is required if using --account-name")
			os.Exit(-1)
		}
		if migratePublicSubnets == "" {
			fmt.Println("--public-subnets is required if using --account-name")
			os.Exit(-1)
		}
	}

	username, token, err := Login()
	check(err)

	shipment := args[0]
	env := args[1]

	//validate that the "app-env" name (used for alb name) is <= 32 characters
	app := shipment
	if migrateAppName != "" {
		app = migrateAppName
	}
	appEnv := fmt.Sprintf("%s-%s", app, env)
	if len(appEnv) > 32 {
		check(fmt.Errorf("%s (app-env) must be <= 32 characters", appEnv))
	}

	//instantiate a build provider if specified
	var provider *BuildProvider
	if len(migrateBuildProvider) > 0 {
		temp, err := getBuildProvider(migrateBuildProvider)
		provider = &temp
		check(err)
	}

	if Verbose {
		log.Printf("fetching shipment...")
	}
	shipmentObject := GetShipmentEnvironment(username, token, shipment, env)
	if shipmentObject == nil {
		fmt.Println(messageShipmentEnvironmentNotFound)
		return
	}

	//make all envvars hidden so they get written to hidden.env
	//instead of docker-compose.yml (just to make sure folks don't
	//accidentally check in their secrets)
	hideEnvVars(shipmentObject.ParentShipment.EnvVars)
	hideEnvVars(shipmentObject.EnvVars)
	for _, c := range shipmentObject.Containers {
		hideEnvVars(c.EnvVars)
	}

	//convert a Shipment object into a HarborCompose object
	harborCompose := transformShipmentToHarborCompose(shipmentObject)

	//convert a Shipment object into a DockerCompose object, with hidden envvars
	dockerCompose, hiddenEnvVars := transformShipmentToDockerCompose(shipmentObject)

	if migratePlatform != "ecsfargate" {
		check(errors.New("ecsfargate is the only platform currently supported"))
	}

	//output customized migration template
	targetDir, migrationData := migrateToEcsFargate(shipmentObject, &harborCompose)

	//update image in docker-compose.yml
	for _, v := range dockerCompose.Services {
		v.Image = migrationData.NewImage
	}

	//prompt if the file already exists
	targetDCFile := filepath.Join(targetDir, DockerComposeFile)
	yes := true
	if _, err := os.Stat(targetDCFile); err == nil {
		fmt.Print("docker-compose.yml already exists. Overwrite? ")
		yes = askForConfirmation()
	}
	if yes {
		SerializeDockerCompose(dockerCompose, targetDCFile)
		fmt.Println("wrote " + DockerComposeFile)
	}

	//prompt if the file already exist
	targetHCFile := filepath.Join(targetDir, HarborComposeFile)
	if _, err := os.Stat(targetHCFile); err == nil {
		fmt.Print("harbor-compose.yml already exists. Overwrite? ")
		yes = askForConfirmation()
	}
	if yes {
		SerializeHarborCompose(harborCompose, targetHCFile)
		fmt.Println("wrote " + HarborComposeFile)
	}

	if len(hiddenEnvVars) > 0 {

		//prompt to override hidden env file
		targetHiddenFile := filepath.Join(targetDir, hiddenEnvFileName)
		if _, err := os.Stat(targetHiddenFile); err == nil {
			fmt.Print(targetHiddenFile + " already exists. Overwrite? ")
			yes = askForConfirmation()
		}
		if yes {
			writeEnvFile(hiddenEnvVars, targetHiddenFile)
			fmt.Println("wrote " + targetHiddenFile)
		}

		//add hidden env_file to .gitignore and .dockerignore (to avoid checking in secrets)
		sensitiveFiles := []string{hiddenEnvFileName, ".terraform"}
		appendToFile(".gitignore", sensitiveFiles)
		appendToFile(".dockerignore", sensitiveFiles)
	}

	//if build provider is specified, allow it modify the compose objects and do its thing
	if provider != nil {
		provider, err := getBuildProvider(migrateBuildProvider)
		check(err)

		artifacts, err := provider.ProvideArtifacts(&dockerCompose, &harborCompose, shipmentObject.BuildToken, migratePlatform)
		check(err)

		//write artifacts to file system
		if artifacts != nil {
			for _, artifact := range artifacts {
				//create directories if needed
				dirs := filepath.Dir(artifact.FilePath)
				err = os.MkdirAll(dirs, os.ModePerm)
				check(err)

				if _, err := os.Stat(artifact.FilePath); err == nil {
					//exists
					fmt.Print(artifact.FilePath + " already exists. Overwrite? ")
					if askForConfirmation() {
						err = ioutil.WriteFile(artifact.FilePath, []byte(artifact.FileContents), artifact.FileMode)
						check(err)
					}
				} else {
					//doesn't exist
					err = ioutil.WriteFile(artifact.FilePath, []byte(artifact.FileContents), artifact.FileMode)
					check(err)
				}
			}
		}
	}

	fmt.Println()
	fmt.Println("Run the following commands to provision an matching infrastructure stack on the target platform:")
	fmt.Println("cd infrastructure/base")
	fmt.Println("terraform init")
	fmt.Println("terraform apply")
	fmt.Println("cd ../env/" + env)
	fmt.Println("terraform init")
	fmt.Println("terraform apply")
	fmt.Println()
	fmt.Println("Then run the following script to copy your docker image to ECR:")
	fmt.Println("./migrate-image.sh")
	fmt.Println()
	fmt.Println("Then run the following command to deploy your application image and environment variables:")
	fmt.Println("fargate service deploy -f docker-compose.yml")
	fmt.Println()
	fmt.Println("To integrate with DOC monitoring:")
	fmt.Println("./doc-monitoring.sh on")
	fmt.Println()
	fmt.Println("Once you're comfortable with your new environment, run the following command to turn off your harbor environment:")
	fmt.Println("harbor-compose down")
	fmt.Println()
}
<commit_msg>updates to latest template v0.4.1 (#192)<commit_after>package cmd

import (
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"github.com/spf13/cobra"
)

// migrateCmd represents the migrate command
var migrateCmd = &cobra.Command{
	Use:   "migrate [shipment] [environment]",
	Short: "Migrate a shipment environment to another platform",
	Long: `Migrate a shipment environment to another platform

The migrate command outputs files that are useful for migrating a shipment/environment to another platform.
Note that the migrate command only outputs files and does not perform an actual migration.

The migrate command's --build-provider flag allows you to generate build provider-specific files that allow you to build Docker images and do CI/CD.
`,
	Example: fmt.Sprintf(`harbor-compose migrate my-shipment dev
harbor-compose migrate my-shipment dev --platform ecsfargate --build-provider circleciv2
harbor-compose migrate my-shipment prod --platform ecsfargate
harbor-compose migrate my-shipment prod --platform ecsfargate --role admin
harbor-compose migrate my-shipment prod --template-tag %s
harbor-compose migrate my-shipment prod --app my-fargate-app

# migrate to the specified account
harbor-compose migrate my-shipment prod \
	--account-name my-aws-account \
	--account-id 123456789012 \
	--vpc vpc-123 \
	--private-subnets subnet-123,subnet-456 \
	--public-subnets subnet-789,subnet-012
`, latestTemplateVersion),
	Run:    migrate,
	PreRun: preRunHook,
}

const (
	latestTemplateVersion = "v0.4.1"
)

var migrateBuildProvider string
var migratePlatform string
var migrateRole string
var migrateTemplateTag string
var migrateProfile string
var migrateAccountID string
var migrateAccountName string
var migrateVPC string
var migratePrivateSubnets string
var migratePublicSubnets string
var migrateAppName string

func init() {
	migrateCmd.PersistentFlags().StringVarP(&migratePlatform, "platform", "p", "ecsfargate", "target migration platform")
	migrateCmd.PersistentFlags().StringVarP(&migrateBuildProvider, "build-provider", "b", "", "migrate build provider-specific files that allow you to build Docker images do CI/CD")
	migrateCmd.PersistentFlags().StringVarP(&migrateTemplateTag, "template-tag", "t", latestTemplateVersion, "migrate using specified template")
	migrateCmd.PersistentFlags().StringVarP(&migrateRole, "role", "r", "devops", "migrate using specified aws role")
	migrateCmd.PersistentFlags().StringVar(&migrateProfile, "profile", "", "migrate using specified aws profile")

	migrateCmd.PersistentFlags().StringVarP(&migrateAccountName, "account-name", "n", "", "migrate to the specified Account Name")
	migrateCmd.PersistentFlags().StringVarP(&migrateAccountID, "account-id", "i", "", "migrate to the specified Account ID")
	migrateCmd.PersistentFlags().StringVar(&migrateVPC, "vpc", "", "migrate to the specified VPC ID")
	migrateCmd.PersistentFlags().StringVar(&migratePrivateSubnets, "private-subnets", "", "migrate using the specified private subnets (comma-delimited)")
	migrateCmd.PersistentFlags().StringVar(&migratePublicSubnets, "public-subnets", "", "migrate using the specified public subnets (comma-delimited)")

	migrateCmd.PersistentFlags().StringVarP(&migrateAppName, "app", "a", "", "use this app name instead of shipment name")

	RootCmd.AddCommand(migrateCmd)
}

func migrate(cmd *cobra.Command, args []string) {
	if len(args) < 2 {
		cmd.Help()
		os.Exit(-1)
	}

	//if account-name is specified, then a number of other args are required
	if migrateAccountName != "" {
		if migrateAccountID == "" {
			fmt.Println("--account-id is required if using --account-name")
			os.Exit(-1)
		}
		if migrateVPC == "" {
			fmt.Println("--vpc is required if using --account-name")
			os.Exit(-1)
		}
		if migratePrivateSubnets == "" {
			fmt.Println("--private-subnets is required if using --account-name")
			os.Exit(-1)
		}
		if migratePublicSubnets == "" {
			fmt.Println("--public-subnets is required if using --account-name")
			os.Exit(-1)
		}
	}

	username, token, err := Login()
	check(err)

	shipment := args[0]
	env := args[1]

	//validate that the "app-env" name (used for alb name) is <= 32 characters
	app := shipment
	if migrateAppName != "" {
		app = migrateAppName
	}
	appEnv := fmt.Sprintf("%s-%s", app, env)
	if len(appEnv) > 32 {
		check(fmt.Errorf("%s (app-env) must be <= 32 characters", appEnv))
	}

	//instantiate a build provider if specified
	var provider *BuildProvider
	if len(migrateBuildProvider) > 0 {
		temp, err := getBuildProvider(migrateBuildProvider)
		provider = &temp
		check(err)
	}

	if Verbose {
		log.Printf("fetching shipment...")
	}
	shipmentObject := GetShipmentEnvironment(username, token, shipment, env)
	if shipmentObject == nil {
		fmt.Println(messageShipmentEnvironmentNotFound)
		return
	}

	//make all envvars hidden so they get written to hidden.env
	//instead of docker-compose.yml (just to make sure folks don't
	//accidentally check in their secrets)
	hideEnvVars(shipmentObject.ParentShipment.EnvVars)
	hideEnvVars(shipmentObject.EnvVars)
	for _, c := range shipmentObject.Containers {
		hideEnvVars(c.EnvVars)
	}

	//convert a Shipment object into a HarborCompose object
	harborCompose := transformShipmentToHarborCompose(shipmentObject)

	//convert a Shipment object into a DockerCompose object, with hidden envvars
	dockerCompose, hiddenEnvVars := transformShipmentToDockerCompose(shipmentObject)

	if migratePlatform != "ecsfargate" {
		check(errors.New("ecsfargate is the only platform currently supported"))
	}

	//output customized migration template
	targetDir, migrationData := migrateToEcsFargate(shipmentObject, &harborCompose)

	//update image in docker-compose.yml
	for _, v := range dockerCompose.Services {
		v.Image = migrationData.NewImage
	}

	//prompt if the file already exists
	targetDCFile := filepath.Join(targetDir, DockerComposeFile)
	yes := true
	if _, err := os.Stat(targetDCFile); err == nil {
		fmt.Print("docker-compose.yml already exists. Overwrite? ")
		yes = askForConfirmation()
	}
	if yes {
		SerializeDockerCompose(dockerCompose, targetDCFile)
		fmt.Println("wrote " + DockerComposeFile)
	}

	//prompt if the file already exist
	targetHCFile := filepath.Join(targetDir, HarborComposeFile)
	if _, err := os.Stat(targetHCFile); err == nil {
		fmt.Print("harbor-compose.yml already exists. Overwrite? ")
		yes = askForConfirmation()
	}
	if yes {
		SerializeHarborCompose(harborCompose, targetHCFile)
		fmt.Println("wrote " + HarborComposeFile)
	}

	if len(hiddenEnvVars) > 0 {

		//prompt to override hidden env file
		targetHiddenFile := filepath.Join(targetDir, hiddenEnvFileName)
		if _, err := os.Stat(targetHiddenFile); err == nil {
			fmt.Print(targetHiddenFile + " already exists. Overwrite? ")
			yes = askForConfirmation()
		}
		if yes {
			writeEnvFile(hiddenEnvVars, targetHiddenFile)
			fmt.Println("wrote " + targetHiddenFile)
		}

		//add hidden env_file to .gitignore and .dockerignore (to avoid checking in secrets)
		sensitiveFiles := []string{hiddenEnvFileName, ".terraform"}
		appendToFile(".gitignore", sensitiveFiles)
		appendToFile(".dockerignore", sensitiveFiles)
	}

	//if build provider is specified, allow it modify the compose objects and do its thing
	if provider != nil {
		provider, err := getBuildProvider(migrateBuildProvider)
		check(err)

		artifacts, err := provider.ProvideArtifacts(&dockerCompose, &harborCompose, shipmentObject.BuildToken, migratePlatform)
		check(err)

		//write artifacts to file system
		if artifacts != nil {
			for _, artifact := range artifacts {
				//create directories if needed
				dirs := filepath.Dir(artifact.FilePath)
				err = os.MkdirAll(dirs, os.ModePerm)
				check(err)

				if _, err := os.Stat(artifact.FilePath); err == nil {
					//exists
					fmt.Print(artifact.FilePath + " already exists. Overwrite? ")
					if askForConfirmation() {
						err = ioutil.WriteFile(artifact.FilePath, []byte(artifact.FileContents), artifact.FileMode)
						check(err)
					}
				} else {
					//doesn't exist
					err = ioutil.WriteFile(artifact.FilePath, []byte(artifact.FileContents), artifact.FileMode)
					check(err)
				}
			}
		}
	}

	fmt.Println()
	fmt.Println("Run the following commands to provision an matching infrastructure stack on the target platform:")
	fmt.Println("cd infrastructure/base")
	fmt.Println("terraform init")
	fmt.Println("terraform apply")
	fmt.Println("cd ../env/" + env)
	fmt.Println("terraform init")
	fmt.Println("terraform apply")
	fmt.Println()
	fmt.Println("Then run the following script to copy your docker image to ECR:")
	fmt.Println("./migrate-image.sh")
	fmt.Println()
	fmt.Println("Then run the following command to deploy your application image and environment variables:")
	fmt.Println("fargate service deploy -f docker-compose.yml")
	fmt.Println()
	fmt.Println("To integrate with DOC monitoring:")
	fmt.Println("./doc-monitoring.sh on")
	fmt.Println()
	fmt.Println("Once you're comfortable with your new environment, run the following command to turn off your harbor environment:")
	fmt.Println("harbor-compose down")
	fmt.Println()
}
<|endoftext|>


<commit_before>package cmd

import (
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	"github.com/zaquestion/lab/internal/action"
)

var mrNoteCmd = &cobra.Command{
	Use:              "note [remote] <id>[:<comment_id>]",
	Aliases:          []string{"comment", "reply"},
	Short:            "Add a note or comment to an MR on GitLab",
	Long:             ``,
	Args:             cobra.MinimumNArgs(1),
	PersistentPreRun: LabPersistentPreRun,
	Run:              NoteRunFn,
}

func init() {
	mrNoteCmd.Flags().StringArrayP("message", "m", []string{}, "use the given <msg>; multiple -m are concatenated as separate paragraphs")
	mrNoteCmd.Flags().StringP("file", "F", "", "use the given file as the message")
	mrNoteCmd.Flags().Bool("force-linebreak", false, "append 2 spaces to the end of each line to force markdown linebreaks")
	mrNoteCmd.Flags().Bool("quote", false, "quote note in reply (used with --reply only)")

	mrCmd.AddCommand(mrNoteCmd)
	carapace.Gen(mrNoteCmd).PositionalCompletion(
		action.Remotes(),
		action.MergeRequests(mrList),
	)
}
<commit_msg>mr_note: Fix error with contextual command<commit_after>package cmd

import (
	"github.com/rsteube/carapace"
	"github.com/spf13/cobra"
	"github.com/zaquestion/lab/internal/action"
)

var mrNoteCmd = &cobra.Command{
	Use:              "note [remote] <id>[:<comment_id>]",
	Aliases:          []string{"comment", "reply"},
	Short:            "Add a note or comment to an MR on GitLab",
	Long:             ``,
	PersistentPreRun: LabPersistentPreRun,
	Run:              NoteRunFn,
}

func init() {
	mrNoteCmd.Flags().StringArrayP("message", "m", []string{}, "use the given <msg>; multiple -m are concatenated as separate paragraphs")
	mrNoteCmd.Flags().StringP("file", "F", "", "use the given file as the message")
	mrNoteCmd.Flags().Bool("force-linebreak", false, "append 2 spaces to the end of each line to force markdown linebreaks")
	mrNoteCmd.Flags().Bool("quote", false, "quote note in reply (used with --reply only)")

	mrCmd.AddCommand(mrNoteCmd)
	carapace.Gen(mrNoteCmd).PositionalCompletion(
		action.Remotes(),
		action.MergeRequests(mrList),
	)
}
<|endoftext|>


<commit_before>package cmd

import (
	"context"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/manifoldco/torus-cli/api"
	"github.com/manifoldco/torus-cli/apitypes"
	"github.com/manifoldco/torus-cli/config"
	"github.com/manifoldco/torus-cli/errs"

	"github.com/urfave/cli"
)

func init() {
	profile := cli.Command{
		Name:     "profile",
		Usage:    "Manage your Torus account",
		Category: "ACCOUNT",
		Subcommands: []cli.Command{
			{
				Name:  "view",
				Usage: "View your profile",
				Action: chain(
					ensureDaemon, ensureSession, setUserEnv, profileView,
				),
			},
			{
				Name:  "update",
				Usage: "Update your profile",
				Action: chain(
					ensureDaemon, ensureSession, setUserEnv, profileView,
				),
			},
		},
	}
	Cmds = append(Cmds, profile)
}

// profileView is used to view your account profile
func profileView(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	session, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}

	w := tabwriter.NewWriter(os.Stdout, 2, 0, 1, ' ', 0)
	if session.Type() == apitypes.MachineSession {
		fmt.Fprintf(w, "Machine ID:\t%s\n", session.ID())
		fmt.Fprintf(w, "Machine Token ID:\t%s\n", session.AuthID())
		fmt.Fprintf(w, "Machine Name:\t%s\n\n", session.Username())
	} else {
		fmt.Fprintf(w, "Name:\t%s\n", session.Name())
		fmt.Fprintf(w, "Email:\t%s\n", session.Email())
		fmt.Fprintf(w, "Username:\t%s\n\n", session.Username())
	}

	w.Flush()

	return nil
}

// profileEdit is used to update name and email for an account
func profileEdit(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	session, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}
	if session.Type() == apitypes.MachineSession {
		return errs.NewExitError("Machines cannot update profile")
	}

	ogName := session.Name()
	name, err := FullNamePrompt(ogName)
	if err != nil {
		return err
	}

	ogEmail := session.Email()
	email, err := EmailPrompt(ogEmail)
	if err != nil {
		return err
	}

	warning := "\nYou are about to update your profile to the values above."
	if email != ogEmail {
		warning = "\nYou will be required to re-verify your email address before taking any further actions within Torus."
	}

	if ogEmail == email && ogName == name {
		fmt.Println("\nNo changes made :)")
		return nil
	}

	err = ConfirmDialogue(ctx, nil, &warning)
	if err != nil {
		return err
	}

	delta := apitypes.ProfileUpdate{}
	if ogEmail != email {
		delta.Email = email
	}
	if ogName != name {
		delta.Name = name
	}

	_, err = client.Users.Update(c, delta)
	if err != nil {
		return errs.NewErrorExitError("Failed to update profile.", err)
	}
	updatedSession, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}

	fmt.Println("")
	w := tabwriter.NewWriter(os.Stdout, 2, 0, 1, ' ', 0)
	fmt.Fprintf(w, "Name:\t%s\n", updatedSession.Name())
	fmt.Fprintf(w, "Email:\t%s\n", updatedSession.Email())
	fmt.Fprintf(w, "Username:\t%s\n\n", updatedSession.Username())
	w.Flush()

	return nil
}
<commit_msg>Fix command reference in profile update middleware<commit_after>package cmd

import (
	"context"
	"fmt"
	"os"
	"text/tabwriter"

	"github.com/manifoldco/torus-cli/api"
	"github.com/manifoldco/torus-cli/apitypes"
	"github.com/manifoldco/torus-cli/config"
	"github.com/manifoldco/torus-cli/errs"

	"github.com/urfave/cli"
)

func init() {
	profile := cli.Command{
		Name:     "profile",
		Usage:    "Manage your Torus account",
		Category: "ACCOUNT",
		Subcommands: []cli.Command{
			{
				Name:  "view",
				Usage: "View your profile",
				Action: chain(
					ensureDaemon, ensureSession, setUserEnv, profileView,
				),
			},
			{
				Name:  "update",
				Usage: "Update your profile",
				Action: chain(
					ensureDaemon, ensureSession, setUserEnv, profileEdit,
				),
			},
		},
	}
	Cmds = append(Cmds, profile)
}

// profileView is used to view your account profile
func profileView(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	session, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}

	w := tabwriter.NewWriter(os.Stdout, 2, 0, 1, ' ', 0)
	if session.Type() == apitypes.MachineSession {
		fmt.Fprintf(w, "Machine ID:\t%s\n", session.ID())
		fmt.Fprintf(w, "Machine Token ID:\t%s\n", session.AuthID())
		fmt.Fprintf(w, "Machine Name:\t%s\n\n", session.Username())
	} else {
		fmt.Fprintf(w, "Name:\t%s\n", session.Name())
		fmt.Fprintf(w, "Email:\t%s\n", session.Email())
		fmt.Fprintf(w, "Username:\t%s\n\n", session.Username())
	}

	w.Flush()

	return nil
}

// profileEdit is used to update name and email for an account
func profileEdit(ctx *cli.Context) error {
	cfg, err := config.LoadConfig()
	if err != nil {
		return err
	}

	client := api.NewClient(cfg)
	c := context.Background()

	session, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}
	if session.Type() == apitypes.MachineSession {
		return errs.NewExitError("Machines cannot update profile")
	}

	ogName := session.Name()
	name, err := FullNamePrompt(ogName)
	if err != nil {
		return err
	}

	ogEmail := session.Email()
	email, err := EmailPrompt(ogEmail)
	if err != nil {
		return err
	}

	warning := "\nYou are about to update your profile to the values above."
	if email != ogEmail {
		warning = "\nYou will be required to re-verify your email address before taking any further actions within Torus."
	}

	if ogEmail == email && ogName == name {
		fmt.Println("\nNo changes made :)")
		return nil
	}

	err = ConfirmDialogue(ctx, nil, &warning)
	if err != nil {
		return err
	}

	delta := apitypes.ProfileUpdate{}
	if ogEmail != email {
		delta.Email = email
	}
	if ogName != name {
		delta.Name = name
	}

	_, err = client.Users.Update(c, delta)
	if err != nil {
		return errs.NewErrorExitError("Failed to update profile.", err)
	}
	updatedSession, err := client.Session.Who(c)
	if err != nil {
		return errs.NewErrorExitError("Error fetching user details", err)
	}

	fmt.Println("")
	w := tabwriter.NewWriter(os.Stdout, 2, 0, 1, ' ', 0)
	fmt.Fprintf(w, "Name:\t%s\n", updatedSession.Name())
	fmt.Fprintf(w, "Email:\t%s\n", updatedSession.Email())
	fmt.Fprintf(w, "Username:\t%s\n\n", updatedSession.Username())
	w.Flush()

	return nil
}
<|endoftext|>


<commit_before>package main

const version = "0.2.3"
<commit_msg>Update version.go<commit_after>package main

const version = "2.3"
<|endoftext|>


<commit_before>package cmd

import "github.com/spf13/cobra"

func init() {
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Displays the version of mbt",
	Run: func(cmd *cobra.Command, args []string) {
		println("0.3.0")
	},
}
<commit_msg>Bump version<commit_after>package cmd

import "github.com/spf13/cobra"

func init() {
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Displays the version of mbt",
	Run: func(cmd *cobra.Command, args []string) {
		println("0.4.0")
	},
}
<|endoftext|>