<commit_before>package renter

import (
	"bytes"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"testing"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
)

// newTestingFile initializes a file object with random parameters.
func newTestingFile() *file {
	key, _ := crypto.GenerateTwofishKey()
	data, _ := crypto.RandBytes(8)
	nData, _ := crypto.RandIntn(10)
	nParity, _ := crypto.RandIntn(10)
	rsc, _ := NewRSCode(nData+1, nParity+1)

	return &file{
		name:        "testfile-" + strconv.Itoa(int(data[0])),
		size:        encoding.DecUint64(data[1:5]),
		masterKey:   key,
		erasureCode: rsc,
		pieceSize:   encoding.DecUint64(data[6:8]),
	}
}

// equalFiles is a helper function that compares two files for equality.
func equalFiles(f1, f2 *file) error {
	if f1 == nil || f2 == nil {
		return fmt.Errorf("one or both files are nil")
	}
	if f1.name != f2.name {
		return fmt.Errorf("names do not match: %v %v", f1.name, f2.name)
	}
	if f1.size != f2.size {
		return fmt.Errorf("sizes do not match: %v %v", f1.size, f2.size)
	}
	if f1.masterKey != f2.masterKey {
		return fmt.Errorf("keys do not match: %v %v", f1.masterKey, f2.masterKey)
	}
	if f1.pieceSize != f2.pieceSize {
		return fmt.Errorf("pieceSizes do not match: %v %v", f1.pieceSize, f2.pieceSize)
	}
	return nil
}

// TestFileMarshalling tests the MarshalSia and UnmarshalSia functions of the
// file type.
func TestFileMarshalling(t *testing.T) {
	savedFile := newTestingFile()
	buf := new(bytes.Buffer)
	savedFile.MarshalSia(buf)

	loadedFile := new(file)
	err := loadedFile.UnmarshalSia(buf)
	if err != nil {
		t.Fatal(err)
	}

	err = equalFiles(savedFile, loadedFile)
	if err != nil {
		t.Fatal(err)
	}
}

// TestFileShareLoad tests the sharing/loading functions of the renter.
func TestFileShareLoad(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterShareLoad")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create a file and add it to the renter.
	savedFile := newTestingFile()
	rt.renter.files[savedFile.name] = savedFile

	// Share .sia file to disk.
	path := filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test.sia")
	err = rt.renter.ShareFiles([]string{savedFile.name}, path)
	if err != nil {
		t.Fatal(err)
	}

	// Remove the file from the renter.
	delete(rt.renter.files, savedFile.name)

	// Load the .sia file back into the renter.
	names, err := rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != savedFile.name {
		t.Fatal("nickname not loaded properly:", names)
	}
	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}

	// Share and load multiple files.
	savedFile2 := newTestingFile()
	rt.renter.files[savedFile2.name] = savedFile2
	path = filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test2.sia")
	err = rt.renter.ShareFiles([]string{savedFile.name, savedFile2.name}, path)
	if err != nil {
		t.Fatal(err)
	}

	// Remove the files from the renter.
	delete(rt.renter.files, savedFile.name)
	delete(rt.renter.files, savedFile2.name)

	names, err = rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(nil)
	}
	if len(names) != 2 || (names[0] != savedFile2.name && names[1] != savedFile2.name) {
		t.Fatal("nicknames not loaded properly:", names)
	}
	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}
	err = equalFiles(rt.renter.files[savedFile2.name], savedFile2)
	if err != nil {
		t.Fatal(err)
	}
}

// TestFileShareLoadASCII tests the ASCII sharing/loading functions.
func TestFileShareLoadASCII(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterShareLoadASCII")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create a file and add it to the renter.
	savedFile := newTestingFile()
	rt.renter.files[savedFile.name] = savedFile

	ascii, err := rt.renter.ShareFilesAscii([]string{savedFile.name})
	if err != nil {
		t.Fatal(err)
	}

	// Remove the file from the renter.
	delete(rt.renter.files, savedFile.name)

	names, err := rt.renter.LoadSharedFilesAscii(ascii)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != savedFile.name {
		t.Fatal("nickname not loaded properly")
	}

	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}
}

// TestRenterSaveLoad probes the save and load methods of the renter type.
func TestRenterSaveLoad(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterSaveLoad")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create and save some files
	var f1, f2, f3 *file
	f1 = newTestingFile()
	f2 = newTestingFile()
	f3 = newTestingFile()
	// names must not conflict
	for f2.name == f1.name || f2.name == f3.name {
		f2 = newTestingFile()
	}
	for f3.name == f1.name || f3.name == f2.name {
		f3 = newTestingFile()
	}
	rt.renter.saveFile(f1)
	rt.renter.saveFile(f2)
	rt.renter.saveFile(f3)

	err = rt.renter.save() // save metadata
	if err != nil {
		t.Fatal(err)
	}

	// load should now load the files into memory.
	id := rt.renter.mu.Lock()
	err = rt.renter.load()
	rt.renter.mu.Unlock(id)
	if err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}

	if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil {
		t.Fatal(err)
	}
}

// TestRenterPaths checks that the renter properly handles nicknames
// containing the path separator ("/").
func TestRenterPaths(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterPaths")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create and save some files.
	// The result of saving these files should be a directory containing:
	//   foo.sia
	//   foo/bar.sia
	//   foo/bar/baz.sia
	f1 := newTestingFile()
	f1.name = "foo"
	f2 := newTestingFile()
	f2.name = "foo/bar"
	f3 := newTestingFile()
	f3.name = "foo/bar/baz"
	rt.renter.saveFile(f1)
	rt.renter.saveFile(f2)
	rt.renter.saveFile(f3)

	// Load the files into the renter.
	id := rt.renter.mu.Lock()
	err = rt.renter.load()
	rt.renter.mu.Unlock(id)
	if err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	// Check that the files were loaded properly.
	if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil {
		t.Fatal(err)
	}

	// To confirm that the file structure was preserved, we walk the renter
	// folder and emit the name of each .sia file encountered (filepath.Walk
	// is deterministic; it orders the files lexically).
	var walkStr string
	filepath.Walk(rt.renter.persistDir, func(path string, _ os.FileInfo, _ error) error {
		// capture only .sia files
		if filepath.Ext(path) != ".sia" {
			return nil
		}
		rel, _ := filepath.Rel(rt.renter.persistDir, path) // strip testdir prefix
		walkStr += rel
		return nil
	})
	// walk will descend into foo/bar/, reading baz, bar, and finally foo
	expWalkStr := (f3.name + ".sia") + (f2.name + ".sia") + (f1.name + ".sia")
	if filepath.ToSlash(walkStr) != expWalkStr {
		t.Fatalf("Bad walk string: expected %v, got %v", expWalkStr, walkStr)
	}
}

// TestSiafileCompatibility tests that the renter is able to load v0.4.8 .sia files.
func TestSiafileCompatibility(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestSiafileCompatibility")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Load the compatibility file into the renter.
	path := filepath.Join("..", "..", "compatibility", "siafile_v0.4.8.sia")
	names, err := rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != "testfile-183" {
		t.Fatal("nickname not loaded properly:", names)
	}
}
<commit_msg>thread safety in renter tests<commit_after>package renter

import (
	"bytes"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"testing"

	"github.com/NebulousLabs/Sia/build"
	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/encoding"
)

// newTestingFile initializes a file object with random parameters.
func newTestingFile() *file {
	key, _ := crypto.GenerateTwofishKey()
	data, _ := crypto.RandBytes(8)
	nData, _ := crypto.RandIntn(10)
	nParity, _ := crypto.RandIntn(10)
	rsc, _ := NewRSCode(nData+1, nParity+1)

	return &file{
		name:        "testfile-" + strconv.Itoa(int(data[0])),
		size:        encoding.DecUint64(data[1:5]),
		masterKey:   key,
		erasureCode: rsc,
		pieceSize:   encoding.DecUint64(data[6:8]),
	}
}

// equalFiles is a helper function that compares two files for equality.
func equalFiles(f1, f2 *file) error {
	if f1 == nil || f2 == nil {
		return fmt.Errorf("one or both files are nil")
	}
	if f1.name != f2.name {
		return fmt.Errorf("names do not match: %v %v", f1.name, f2.name)
	}
	if f1.size != f2.size {
		return fmt.Errorf("sizes do not match: %v %v", f1.size, f2.size)
	}
	if f1.masterKey != f2.masterKey {
		return fmt.Errorf("keys do not match: %v %v", f1.masterKey, f2.masterKey)
	}
	if f1.pieceSize != f2.pieceSize {
		return fmt.Errorf("pieceSizes do not match: %v %v", f1.pieceSize, f2.pieceSize)
	}
	return nil
}

// TestFileMarshalling tests the MarshalSia and UnmarshalSia functions of the
// file type.
func TestFileMarshalling(t *testing.T) {
	savedFile := newTestingFile()
	buf := new(bytes.Buffer)
	savedFile.MarshalSia(buf)

	loadedFile := new(file)
	err := loadedFile.UnmarshalSia(buf)
	if err != nil {
		t.Fatal(err)
	}

	err = equalFiles(savedFile, loadedFile)
	if err != nil {
		t.Fatal(err)
	}
}

// TestFileShareLoad tests the sharing/loading functions of the renter.
func TestFileShareLoad(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterShareLoad")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create a file and add it to the renter.
	savedFile := newTestingFile()
	id := rt.renter.mu.Lock()
	rt.renter.files[savedFile.name] = savedFile
	rt.renter.mu.Unlock(id)

	// Share .sia file to disk.
	path := filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test.sia")
	err = rt.renter.ShareFiles([]string{savedFile.name}, path)
	if err != nil {
		t.Fatal(err)
	}

	// Remove the file from the renter.
	delete(rt.renter.files, savedFile.name)

	// Load the .sia file back into the renter.
	names, err := rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != savedFile.name {
		t.Fatal("nickname not loaded properly:", names)
	}
	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}

	// Share and load multiple files.
	savedFile2 := newTestingFile()
	rt.renter.files[savedFile2.name] = savedFile2
	path = filepath.Join(build.SiaTestingDir, "renter", "TestRenterShareLoad", "test2.sia")
	err = rt.renter.ShareFiles([]string{savedFile.name, savedFile2.name}, path)
	if err != nil {
		t.Fatal(err)
	}

	// Remove the files from the renter.
	delete(rt.renter.files, savedFile.name)
	delete(rt.renter.files, savedFile2.name)

	names, err = rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(nil)
	}
	if len(names) != 2 || (names[0] != savedFile2.name && names[1] != savedFile2.name) {
		t.Fatal("nicknames not loaded properly:", names)
	}
	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}
	err = equalFiles(rt.renter.files[savedFile2.name], savedFile2)
	if err != nil {
		t.Fatal(err)
	}
}

// TestFileShareLoadASCII tests the ASCII sharing/loading functions.
func TestFileShareLoadASCII(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterShareLoadASCII")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create a file and add it to the renter.
	savedFile := newTestingFile()
	id := rt.renter.mu.Lock()
	rt.renter.files[savedFile.name] = savedFile
	rt.renter.mu.Unlock(id)

	ascii, err := rt.renter.ShareFilesAscii([]string{savedFile.name})
	if err != nil {
		t.Fatal(err)
	}

	// Remove the file from the renter.
	delete(rt.renter.files, savedFile.name)

	names, err := rt.renter.LoadSharedFilesAscii(ascii)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != savedFile.name {
		t.Fatal("nickname not loaded properly")
	}

	err = equalFiles(rt.renter.files[savedFile.name], savedFile)
	if err != nil {
		t.Fatal(err)
	}
}

// TestRenterSaveLoad probes the save and load methods of the renter type.
func TestRenterSaveLoad(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterSaveLoad")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create and save some files
	var f1, f2, f3 *file
	f1 = newTestingFile()
	f2 = newTestingFile()
	f3 = newTestingFile()
	// names must not conflict
	for f2.name == f1.name || f2.name == f3.name {
		f2 = newTestingFile()
	}
	for f3.name == f1.name || f3.name == f2.name {
		f3 = newTestingFile()
	}
	rt.renter.saveFile(f1)
	rt.renter.saveFile(f2)
	rt.renter.saveFile(f3)

	err = rt.renter.save() // save metadata
	if err != nil {
		t.Fatal(err)
	}

	// load should now load the files into memory.
	id := rt.renter.mu.Lock()
	err = rt.renter.load()
	rt.renter.mu.Unlock(id)
	if err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}

	if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil {
		t.Fatal(err)
	}
}

// TestRenterPaths checks that the renter properly handles nicknames
// containing the path separator ("/").
func TestRenterPaths(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestRenterPaths")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Create and save some files.
	// The result of saving these files should be a directory containing:
	//   foo.sia
	//   foo/bar.sia
	//   foo/bar/baz.sia
	f1 := newTestingFile()
	f1.name = "foo"
	f2 := newTestingFile()
	f2.name = "foo/bar"
	f3 := newTestingFile()
	f3.name = "foo/bar/baz"
	rt.renter.saveFile(f1)
	rt.renter.saveFile(f2)
	rt.renter.saveFile(f3)

	// Load the files into the renter.
	id := rt.renter.mu.Lock()
	err = rt.renter.load()
	rt.renter.mu.Unlock(id)
	if err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	// Check that the files were loaded properly.
	if err := equalFiles(f1, rt.renter.files[f1.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f2, rt.renter.files[f2.name]); err != nil {
		t.Fatal(err)
	}
	if err := equalFiles(f3, rt.renter.files[f3.name]); err != nil {
		t.Fatal(err)
	}

	// To confirm that the file structure was preserved, we walk the renter
	// folder and emit the name of each .sia file encountered (filepath.Walk
	// is deterministic; it orders the files lexically).
	var walkStr string
	filepath.Walk(rt.renter.persistDir, func(path string, _ os.FileInfo, _ error) error {
		// capture only .sia files
		if filepath.Ext(path) != ".sia" {
			return nil
		}
		rel, _ := filepath.Rel(rt.renter.persistDir, path) // strip testdir prefix
		walkStr += rel
		return nil
	})
	// walk will descend into foo/bar/, reading baz, bar, and finally foo
	expWalkStr := (f3.name + ".sia") + (f2.name + ".sia") + (f1.name + ".sia")
	if filepath.ToSlash(walkStr) != expWalkStr {
		t.Fatalf("Bad walk string: expected %v, got %v", expWalkStr, walkStr)
	}
}

// TestSiafileCompatibility tests that the renter is able to load v0.4.8 .sia files.
func TestSiafileCompatibility(t *testing.T) {
	if testing.Short() {
		t.SkipNow()
	}
	rt, err := newRenterTester("TestSiafileCompatibility")
	if err != nil {
		t.Fatal(err)
	}
	defer rt.Close()

	// Load the compatibility file into the renter.
	path := filepath.Join("..", "..", "compatibility", "siafile_v0.4.8.sia")
	names, err := rt.renter.LoadSharedFiles(path)
	if err != nil {
		t.Fatal(err)
	}
	if len(names) != 1 || names[0] != "testfile-183" {
		t.Fatal("nickname not loaded properly:", names)
	}
}
<|endoftext|>


<commit_before>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package applescript

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

	"github.com/bogem/nehm/logs"
)

const (
	script = `
on run argv
	set commandType to first item of argv as string
	if (commandType is equal to "add_track_to_playlist") then
		add_track_to_playlist(second item of argv, third item of argv)
	end if
	if (commandType is equal to "list_of_playlists") then
		list_of_playlists()
	end if
end run

on add_track_to_playlist(trackPath, playlistName)
	tell application "iTunes"
		add (trackPath as POSIX file) to playlist playlistName
	end tell
end add_track_to_playlist

on list_of_playlists()
	tell application "iTunes"
		get name of playlists
	end tell
end list_of_playlists
`
)

var scriptFile *os.File

func AddTrackToPlaylist(trackPath, playlistName string) error {
	_, err := executeOSAScript("add_track_to_playlist", trackPath, playlistName)
	return err
}

func ListOfPlaylists() (string, error) {
	return executeOSAScript("list_of_playlists")
}

// executeOSAScript executes AppleScript script with args and returns output and error.
func executeOSAScript(args ...string) (string, error) {
	if scriptFile == nil {
		var err error
		scriptFile, err = ioutil.TempFile("", "")
		if err != nil {
			return "", fmt.Errorf("couldn't create osascript file: %v", err)
		}
		if _, err = scriptFile.Write([]byte(script)); err != nil {
			return "", fmt.Errorf("couldn't write script to file: %v", err)
		}
	}

	args = append([]string{scriptFile.Name()}, args...)
	logs.DEBUG.Println("Executing osascript with args :", args)
	out, err := exec.Command("osascript", args...).CombinedOutput()
	return string(out), err
}
<commit_msg>applescript: Delete log and make better errors<commit_after>// Copyright 2016 Albert Nigmatzianov. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package applescript

import (
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
)

const (
	script = `
on run argv
	set commandType to first item of argv as string
	if (commandType is equal to "add_track_to_playlist") then
		add_track_to_playlist(second item of argv, third item of argv)
	end if
	if (commandType is equal to "list_of_playlists") then
		list_of_playlists()
	end if
end run

on add_track_to_playlist(trackPath, playlistName)
	tell application "iTunes"
		add (trackPath as POSIX file) to playlist playlistName
	end tell
end add_track_to_playlist

on list_of_playlists()
	tell application "iTunes"
		get name of playlists
	end tell
end list_of_playlists
`
)

var scriptFile *os.File

func AddTrackToPlaylist(trackPath, playlistName string) error {
	out, _ := executeOSAScript("add_track_to_playlist", "./"+trackPath, playlistName)
	return errors.New(out)
}

func ListOfPlaylists() (string, error) {
	return executeOSAScript("list_of_playlists")
}

// executeOSAScript executes AppleScript script with args and returns output and error.
func executeOSAScript(args ...string) (string, error) {
	if scriptFile == nil {
		var err error
		scriptFile, err = ioutil.TempFile("", "")
		if err != nil {
			return "", fmt.Errorf("couldn't create osascript file: %v", err)
		}
		if _, err = scriptFile.Write([]byte(script)); err != nil {
			return "", fmt.Errorf("couldn't write script to file: %v", err)
		}
	}

	args = append([]string{scriptFile.Name()}, args...)
	out, err := exec.Command("osascript", args...).CombinedOutput()
	return string(out), err
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"fmt"
	"github.com/nicholasjackson/blackpuppy-api-mail/business"
	"github.com/nicholasjackson/blackpuppy-api-mail/email"
)

func ContactUsHandler(rw http.ResponseWriter, r *http.Request) {
	response := business.ContactUsResponse{}
	response.StatusMessage = "OK"

	encoder := json.NewEncoder(rw)

	data, _ := ioutil.ReadAll(r.Body)
	var contactUsRequest business.ContactUsRequest

	err := json.Unmarshal(data, &contactUsRequest)
	if err != nil || !business.ValidateRequest(&contactUsRequest) {
		http.Error(rw, "Invalid request object", http.StatusBadRequest)
		return
	}

	mail := email.SmtpMail{}

	err = business.SendEmail(contactUsRequest.Name, contactUsRequest.Email, contactUsRequest.Body, &mail)

	if err != nil {
		fmt.Printf("%v\n", err.Error())
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	encoder.Encode(&response)
}
<commit_msg>added coors headers<commit_after>package handlers

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/nicholasjackson/blackpuppy-api-mail/business"
	"github.com/nicholasjackson/blackpuppy-api-mail/email"
)

func ContactUsHandler(rw http.ResponseWriter, r *http.Request) {
	rw.Header().Set("Access-Control-Allow-Origin", "*")

	response := business.ContactUsResponse{}
	response.StatusMessage = "OK"

	encoder := json.NewEncoder(rw)

	data, _ := ioutil.ReadAll(r.Body)
	var contactUsRequest business.ContactUsRequest

	err := json.Unmarshal(data, &contactUsRequest)
	if err != nil || !business.ValidateRequest(&contactUsRequest) {
		http.Error(rw, "Invalid request object", http.StatusBadRequest)
		return
	}

	mail := email.SmtpMail{}

	err = business.SendEmail(contactUsRequest.Name, contactUsRequest.Email, contactUsRequest.Body, &mail)

	if err != nil {
		fmt.Printf("%v\n", err.Error())
		http.Error(rw, err.Error(), http.StatusInternalServerError)
		return
	}

	encoder.Encode(&response)
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/workers/payment/paymentmodels"

	"github.com/koding/kite"
)

type requestArgs struct {
	MachineId string `json:"machineId"`
	Reason    string `json:"reason"`
}

func stopMachinesForUser(customerId string, k *kite.Client) error {
	customer := paymentmodels.NewCustomer()
	err := customer.ByProviderCustomerId(customerId)
	if err != nil {
		return err
	}

	username := customer.Username
	if isUsernameEmpty(username) {
		return errUsernameEmpty(username)
	}

	machines, err := modelhelper.GetMachinesForUsername(username)
	if err != nil {
		return err
	}

	if k == nil {
		Log.Info("Klient not initialized. Not stopping machines for user: %s",
			username,
		)

		return nil
	}

	for _, machine := range machines {
		_, err := k.Tell("stop", &requestArgs{
			MachineId: machine.ObjectId.Hex(), Reason: "Plan expired",
		})

		if err != nil {
			Log.Error("Error stopping machine:%s for username: %s, %v", username, machine, err)
		}
	}

	return nil
}

//----------------------------------------------------------
// Helpers
//----------------------------------------------------------

func isUsernameEmpty(username string) bool {
	return username == ""
}

func errUsernameEmpty(customerId string) error {
	return fmt.Errorf(
		"stopping machine for paypal customer: %s failed since username is empty",
		customerId,
	)
}

func errUnmarshalFailed(data interface{}) error {
	return fmt.Errorf("unmarshalling webhook failed: %v", data)
}
<commit_msg>paymentwebhook: when trying to stop vm, ignore error if vm is  already stopped<commit_after>package main

import (
	"fmt"
	"koding/db/mongodb/modelhelper"
	"socialapi/workers/payment/paymentmodels"
	"strings"

	"github.com/koding/kite"
)

type requestArgs struct {
	MachineId string `json:"machineId"`
	Reason    string `json:"reason"`
}

func stopMachinesForUser(customerId string, k *kite.Client) error {
	customer := paymentmodels.NewCustomer()
	err := customer.ByProviderCustomerId(customerId)
	if err != nil {
		return err
	}

	username := customer.Username
	if isUsernameEmpty(username) {
		return errUsernameEmpty(username)
	}

	machines, err := modelhelper.GetMachinesForUsername(username)
	if err != nil {
		return err
	}

	if k == nil {
		Log.Info("Klient not initialized. Not stopping machines for user: %s",
			username,
		)

		return nil
	}

	for _, machine := range machines {
		_, err := k.Tell("stop", &requestArgs{
			MachineId: machine.ObjectId.Hex(), Reason: "Plan expired",
		})

		if err != nil && !isVmAlreadyStoppedErr(err) {
			Log.Error("Error stopping machine:%s for username: %s, %v", username, machine, err)
		}
	}

	return nil
}

//----------------------------------------------------------
// Helpers
//----------------------------------------------------------

func isUsernameEmpty(username string) bool {
	return username == ""
}

func errUsernameEmpty(customerId string) error {
	return fmt.Errorf(
		"stopping machine for paypal customer: %s failed since username is empty",
		customerId,
	)
}

func errUnmarshalFailed(data interface{}) error {
	return fmt.Errorf("unmarshalling webhook failed: %v", data)
}

func isVmAlreadyStoppedErr(err error) bool {
	return err != nil && strings.Contains(err.Error(), "not allowed for current state")
}
<|endoftext|>


<commit_before>// Copyright 2013 Google Inc. 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 drive

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	gopath "path"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	spinner "github.com/odeke-em/cli-spinner"
	"github.com/odeke-em/drive/config"
)

// Pushes to remote if local path exists and in a gd context. If path is a
// directory, it recursively pushes to the remote if there are local changes.
// It doesn't check if there are local changes if isForce is set.
func (g *Commands) Push() (err error) {
	defer g.clearMountPoints()

	root := g.context.AbsPathOf("")
	var cl []*Change

	fmt.Println("Resolving...")
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	spin := spinner.New(10)
	spin.Start()

	// To Ensure mount points are cleared in the event of external exceptios
	go func() {
		_ = <-c
		spin.Stop()
		g.clearMountPoints()
		os.Exit(1)
	}()

	for _, relToRootPath := range g.opts.Sources {
		fsPath := g.context.AbsPathOf(relToRootPath)
		ccl, cErr := g.changeListResolve(relToRootPath, fsPath, true)
		if cErr != nil {
			spin.Stop()
			return cErr
		}
		if len(ccl) > 0 {
			cl = append(cl, ccl...)
		}
	}

	mount := g.opts.Mount
	if mount != nil {
		for _, mt := range mount.Points {
			ccl, cerr := lonePush(g, root, mt.Name, mt.MountPath)
			if cerr == nil {
				cl = append(cl, ccl...)
			}
		}
	}

	spin.Stop()

	nonConflictsPtr, conflictsPtr := g.resolveConflicts(cl)
	if conflictsPtr != nil {
		warnConflictsPersist(*conflictsPtr)
		return
	}

	nonConflicts := *nonConflictsPtr

	ok := printChangeList(nonConflicts, g.opts.NoPrompt, g.opts.NoClobber)
	if !ok {
		return
	}

	pushSize := reduceToSize(cl, true)

	quotaStatus, qErr := g.QuotaStatus(pushSize)
	if qErr != nil {
		return qErr
	}
	unSafe := false
	switch quotaStatus {
	case AlmostExceeded:
		fmt.Println("\033[92mAlmost exceeding your drive quota\033[00m")
	case Exceeded:
		fmt.Println("\033[91mThis change will exceed your drive quota\033[00m")
		unSafe = true
	}
	if unSafe {
		fmt.Printf(" projected size: %d (%d)\n", pushSize, prettyBytes(pushSize))
		if !promptForChanges() {
			return
		}
	}
	return g.playPushChangeList(nonConflicts)
}

func (g *Commands) resolveConflicts(cl []*Change) (*[]*Change, *[]*Change) {
	if g.opts.IgnoreConflict {
		return &cl, nil
	}

	nonConflicts, conflicts := sift(cl)
	resolved, unresolved := resolveConflicts(conflicts, true, g.deserializeIndex)
	if conflictsPersist(unresolved) {
		return &resolved, &unresolved
	}

	for _, ch := range unresolved {
		resolved = append(resolved, ch)
	}

	for _, ch := range resolved {
		nonConflicts = append(nonConflicts, ch)
	}
	return &nonConflicts, nil
}

func (g *Commands) PushPiped() (err error) {
	// Cannot push asynchronously because the pull order must be maintained
	for _, relToRootPath := range g.opts.Sources {
		rem, resErr := g.rem.FindByPath(relToRootPath)
		if resErr != nil && resErr != ErrPathNotExists {
			return resErr
		}

		if hasExportLinks(rem) {
			fmt.Printf("'%s' is a GoogleDoc/Sheet document cannot be pushed to raw.\n", relToRootPath)
			continue
		}

		base := filepath.Base(relToRootPath)
		local := fauxLocalFile(base)
		if rem == nil {
			rem = local
		}

		parentPath := g.parentPather(relToRootPath)
		parent, pErr := g.rem.FindByPath(parentPath)
		if pErr != nil {
			spin := spinner.New(10)
			spin.Start()
			parent, pErr = g.remoteMkdirAll(parentPath)
			spin.Stop()
			if pErr != nil || parent == nil {
				fmt.Printf("%s: %v", relToRootPath, pErr)
				return
			}
		}

		args := upsertOpt{
			parentId:       parent.Id,
			fsAbsPath:      relToRootPath,
			src:            rem,
			dest:           rem,
			mask:           g.opts.TypeMask,
			ignoreChecksum: g.opts.IgnoreChecksum,
		}

		rem, rErr := g.rem.upsertByComparison(os.Stdin, &args)
		if rErr != nil {
			fmt.Printf("%s: %v\n", relToRootPath, rErr)
			return rErr
		}
		if rem == nil {
			continue
		}
		index := rem.ToIndex()
		wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

		// TODO: Should indexing errors be reported?
		if wErr != nil {
			fmt.Printf("serializeIndex %s: %v\n", rem.Name, wErr)
		}
	}
	return
}

func (g *Commands) deserializeIndex(identifier string) *config.Index {
	index, err := g.context.DeserializeIndex(g.context.AbsPathOf(""), identifier)
	if err != nil {
		return nil
	}
	return index
}

func (g *Commands) playPushChangeList(cl []*Change) (err error) {
	g.taskStart(len(cl))

	// TODO: Only provide precedence ordering if all the other options are allowed
	// Currently noop on sorting by precedence
	if false && !g.opts.NoClobber {
		sort.Sort(ByPrecedence(cl))
	}

	for _, c := range cl {
		switch c.Op() {
		case OpMod:
			g.remoteMod(c)
		case OpModConflict:
			g.remoteMod(c)
		case OpAdd:
			g.remoteAdd(c)
		case OpDelete:
			g.remoteDelete(c)
		}
	}

	// Time to organize them according branching
	g.taskFinish()
	return err
}

func lonePush(g *Commands, parent, absPath, path string) (cl []*Change, err error) {
	r, err := g.rem.FindByPath(absPath)
	if err != nil && err != ErrPathNotExists {
		return
	}

	var l *File
	localinfo, _ := os.Stat(path)
	if localinfo != nil {
		l = NewLocalFile(path, localinfo)
	}

	return g.resolveChangeListRecv(true, parent, absPath, r, l)
}

func (g *Commands) pathSplitter(absPath string) (dir, base string) {
	p := strings.Split(absPath, "/")
	pLen := len(p)
	base = p[pLen-1]
	p = append([]string{"/"}, p[:pLen-1]...)
	dir = gopath.Join(p...)
	return
}

func (g *Commands) parentPather(absPath string) string {
	dir, _ := g.pathSplitter(absPath)
	return dir
}

func (g *Commands) remoteMod(change *Change) (err error) {
	defer g.taskDone()

	if change.Dest == nil && change.Src == nil {
		err = fmt.Errorf("bug on: both dest and src cannot be nil")
		fmt.Println(err)
		return err
	}

	absPath := g.context.AbsPathOf(change.Path)
	var parent *File
	if change.Dest != nil && change.Src != nil {
		change.Src.Id = change.Dest.Id // TODO: bad hack
	}

	parentPath := g.parentPather(change.Path)
	parent, err = g.rem.FindByPath(parentPath)

	if err != nil {
		return err
	}

	args := upsertOpt{
		parentId:       parent.Id,
		fsAbsPath:      absPath,
		src:            change.Src,
		dest:           change.Dest,
		mask:           g.opts.TypeMask,
		ignoreChecksum: g.opts.IgnoreChecksum,
	}

	rem, err := g.rem.UpsertByComparison(&args)
	if err != nil {
		fmt.Printf("%s: %v\n", change.Path, err)
		return
	}
	if rem == nil {
		return
	}
	index := rem.ToIndex()
	wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

	// TODO: Should indexing errors be reported?
	if wErr != nil {
		fmt.Printf("serializeIndex %s: %v\n", rem.Name, wErr)
	}
	return
}

func (g *Commands) remoteAdd(change *Change) (err error) {
	return g.remoteMod(change)
}

func (g *Commands) indexAbsPath(fileId string) string {
	return config.IndicesAbsPath(g.context.AbsPathOf(""), fileId)
}

func (g *Commands) remoteUntrash(change *Change) (err error) {
	defer g.taskDone()

	return g.rem.Untrash(change.Src.Id)
}

func (g *Commands) remoteDelete(change *Change) (err error) {
	defer g.taskDone()

	err = g.rem.Trash(change.Dest.Id)
	if err != nil {
		return
	}

	indexPath := g.indexAbsPath(change.Dest.Id)
	if rmErr := os.Remove(indexPath); rmErr != nil {
		fmt.Printf("%s \"%s\": remove indexfile %v\n", change.Path, change.Dest.Id, rmErr)
	}
	return
}

func (g *Commands) remoteMkdirAll(d string) (file *File, err error) {
	// Try the lookup one last time in case a coroutine raced us to it.
	retrFile, retryErr := g.rem.FindByPath(d)
	if retryErr == nil && retrFile != nil {
		return retrFile, nil
	}

	rest, last := remotePathSplit(d)

	parent, parentErr := g.rem.FindByPath(rest)
	if parentErr != nil && parentErr != ErrPathNotExists {
		return parent, parentErr
	}

	if parent == nil {
		parent, parentErr = g.remoteMkdirAll(rest)
		if parentErr != nil || parent == nil {
			return parent, parentErr
		}
	}

	remoteFile := &File{
		IsDir:   true,
		Name:    last,
		ModTime: time.Now(),
	}

	args := upsertOpt{
		parentId: parent.Id,
		src:      remoteFile,
	}
	parent, parentErr = g.rem.UpsertByComparison(&args)
	if parentErr == nil && parent != nil {
		index := parent.ToIndex()
		wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

		// TODO: Should indexing errors be reported?
		if wErr != nil {
			fmt.Printf("serializeIndex %s: %v\n", parent.Name, wErr)
		}
	}
	return parent, parentErr
}

func list(context *config.Context, p string, hidden bool, ignore *regexp.Regexp) (fileChan chan *File, err error) {
	absPath := context.AbsPathOf(p)
	var f []os.FileInfo
	f, err = ioutil.ReadDir(absPath)
	fileChan = make(chan *File)
	if err != nil {
		close(fileChan)
		return
	}

	go func() {
		for _, file := range f {
			if file.Name() == config.GDDirSuffix {
				continue
			}
			if ignore != nil && ignore.Match([]byte(file.Name())) {
				continue
			}
			if !isHidden(file.Name(), hidden) {
				fileChan <- NewLocalFile(gopath.Join(absPath, file.Name()), file)
			}
		}
		close(fileChan)
	}()
	return
}
<commit_msg>push-piped: reject implicit overrides<commit_after>// Copyright 2013 Google Inc. 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 drive

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/signal"
	gopath "path"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	spinner "github.com/odeke-em/cli-spinner"
	"github.com/odeke-em/drive/config"
)

// Pushes to remote if local path exists and in a gd context. If path is a
// directory, it recursively pushes to the remote if there are local changes.
// It doesn't check if there are local changes if isForce is set.
func (g *Commands) Push() (err error) {
	defer g.clearMountPoints()

	root := g.context.AbsPathOf("")
	var cl []*Change

	fmt.Println("Resolving...")
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)

	spin := spinner.New(10)
	spin.Start()

	// To Ensure mount points are cleared in the event of external exceptios
	go func() {
		_ = <-c
		spin.Stop()
		g.clearMountPoints()
		os.Exit(1)
	}()

	for _, relToRootPath := range g.opts.Sources {
		fsPath := g.context.AbsPathOf(relToRootPath)
		ccl, cErr := g.changeListResolve(relToRootPath, fsPath, true)
		if cErr != nil {
			spin.Stop()
			return cErr
		}
		if len(ccl) > 0 {
			cl = append(cl, ccl...)
		}
	}

	mount := g.opts.Mount
	if mount != nil {
		for _, mt := range mount.Points {
			ccl, cerr := lonePush(g, root, mt.Name, mt.MountPath)
			if cerr == nil {
				cl = append(cl, ccl...)
			}
		}
	}

	spin.Stop()

	nonConflictsPtr, conflictsPtr := g.resolveConflicts(cl)
	if conflictsPtr != nil {
		warnConflictsPersist(*conflictsPtr)
		return
	}

	nonConflicts := *nonConflictsPtr

	ok := printChangeList(nonConflicts, g.opts.NoPrompt, g.opts.NoClobber)
	if !ok {
		return
	}

	pushSize := reduceToSize(cl, true)

	quotaStatus, qErr := g.QuotaStatus(pushSize)
	if qErr != nil {
		return qErr
	}
	unSafe := false
	switch quotaStatus {
	case AlmostExceeded:
		fmt.Println("\033[92mAlmost exceeding your drive quota\033[00m")
	case Exceeded:
		fmt.Println("\033[91mThis change will exceed your drive quota\033[00m")
		unSafe = true
	}
	if unSafe {
		fmt.Printf(" projected size: %d (%d)\n", pushSize, prettyBytes(pushSize))
		if !promptForChanges() {
			return
		}
	}
	return g.playPushChangeList(nonConflicts)
}

func (g *Commands) resolveConflicts(cl []*Change) (*[]*Change, *[]*Change) {
	if g.opts.IgnoreConflict {
		return &cl, nil
	}

	nonConflicts, conflicts := sift(cl)
	resolved, unresolved := resolveConflicts(conflicts, true, g.deserializeIndex)
	if conflictsPersist(unresolved) {
		return &resolved, &unresolved
	}

	for _, ch := range unresolved {
		resolved = append(resolved, ch)
	}

	for _, ch := range resolved {
		nonConflicts = append(nonConflicts, ch)
	}
	return &nonConflicts, nil
}

func (g *Commands) PushPiped() (err error) {
	// Cannot push asynchronously because the push order must be maintained
	for _, relToRootPath := range g.opts.Sources {
		rem, resErr := g.rem.FindByPath(relToRootPath)
		if resErr != nil && resErr != ErrPathNotExists {
			return resErr
		}
		if rem != nil && !g.opts.Force {
			fmt.Printf("%s already exists remotely, use `%s` to override this behaviour.\n", relToRootPath, ForceKey)
			continue
		}

		if hasExportLinks(rem) {
			fmt.Printf("'%s' is a GoogleDoc/Sheet document cannot be pushed to raw.\n", relToRootPath)
			continue
		}

		base := filepath.Base(relToRootPath)
		local := fauxLocalFile(base)
		if rem == nil {
			rem = local
		}

		parentPath := g.parentPather(relToRootPath)
		parent, pErr := g.rem.FindByPath(parentPath)
		if pErr != nil {
			spin := spinner.New(10)
			spin.Start()
			parent, pErr = g.remoteMkdirAll(parentPath)
			spin.Stop()
			if pErr != nil || parent == nil {
				fmt.Printf("%s: %v", relToRootPath, pErr)
				return
			}
		}

		args := upsertOpt{
			parentId:       parent.Id,
			fsAbsPath:      relToRootPath,
			src:            rem,
			dest:           rem,
			mask:           g.opts.TypeMask,
			ignoreChecksum: g.opts.IgnoreChecksum,
		}

		rem, rErr := g.rem.upsertByComparison(os.Stdin, &args)
		if rErr != nil {
			fmt.Printf("%s: %v\n", relToRootPath, rErr)
			return rErr
		}
		if rem == nil {
			continue
		}
		index := rem.ToIndex()
		wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

		// TODO: Should indexing errors be reported?
		if wErr != nil {
			fmt.Printf("serializeIndex %s: %v\n", rem.Name, wErr)
		}
	}
	return
}

func (g *Commands) deserializeIndex(identifier string) *config.Index {
	index, err := g.context.DeserializeIndex(g.context.AbsPathOf(""), identifier)
	if err != nil {
		return nil
	}
	return index
}

func (g *Commands) playPushChangeList(cl []*Change) (err error) {
	g.taskStart(len(cl))

	// TODO: Only provide precedence ordering if all the other options are allowed
	// Currently noop on sorting by precedence
	if false && !g.opts.NoClobber {
		sort.Sort(ByPrecedence(cl))
	}

	for _, c := range cl {
		switch c.Op() {
		case OpMod:
			g.remoteMod(c)
		case OpModConflict:
			g.remoteMod(c)
		case OpAdd:
			g.remoteAdd(c)
		case OpDelete:
			g.remoteDelete(c)
		}
	}

	// Time to organize them according branching
	g.taskFinish()
	return err
}

func lonePush(g *Commands, parent, absPath, path string) (cl []*Change, err error) {
	r, err := g.rem.FindByPath(absPath)
	if err != nil && err != ErrPathNotExists {
		return
	}

	var l *File
	localinfo, _ := os.Stat(path)
	if localinfo != nil {
		l = NewLocalFile(path, localinfo)
	}

	return g.resolveChangeListRecv(true, parent, absPath, r, l)
}

func (g *Commands) pathSplitter(absPath string) (dir, base string) {
	p := strings.Split(absPath, "/")
	pLen := len(p)
	base = p[pLen-1]
	p = append([]string{"/"}, p[:pLen-1]...)
	dir = gopath.Join(p...)
	return
}

func (g *Commands) parentPather(absPath string) string {
	dir, _ := g.pathSplitter(absPath)
	return dir
}

func (g *Commands) remoteMod(change *Change) (err error) {
	defer g.taskDone()

	if change.Dest == nil && change.Src == nil {
		err = fmt.Errorf("bug on: both dest and src cannot be nil")
		fmt.Println(err)
		return err
	}

	absPath := g.context.AbsPathOf(change.Path)
	var parent *File
	if change.Dest != nil && change.Src != nil {
		change.Src.Id = change.Dest.Id // TODO: bad hack
	}

	parentPath := g.parentPather(change.Path)
	parent, err = g.rem.FindByPath(parentPath)

	if err != nil {
		return err
	}

	args := upsertOpt{
		parentId:       parent.Id,
		fsAbsPath:      absPath,
		src:            change.Src,
		dest:           change.Dest,
		mask:           g.opts.TypeMask,
		ignoreChecksum: g.opts.IgnoreChecksum,
	}

	rem, err := g.rem.UpsertByComparison(&args)
	if err != nil {
		fmt.Printf("%s: %v\n", change.Path, err)
		return
	}
	if rem == nil {
		return
	}
	index := rem.ToIndex()
	wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

	// TODO: Should indexing errors be reported?
	if wErr != nil {
		fmt.Printf("serializeIndex %s: %v\n", rem.Name, wErr)
	}
	return
}

func (g *Commands) remoteAdd(change *Change) (err error) {
	return g.remoteMod(change)
}

func (g *Commands) indexAbsPath(fileId string) string {
	return config.IndicesAbsPath(g.context.AbsPathOf(""), fileId)
}

func (g *Commands) remoteUntrash(change *Change) (err error) {
	defer g.taskDone()

	return g.rem.Untrash(change.Src.Id)
}

func (g *Commands) remoteDelete(change *Change) (err error) {
	defer g.taskDone()

	err = g.rem.Trash(change.Dest.Id)
	if err != nil {
		return
	}

	indexPath := g.indexAbsPath(change.Dest.Id)
	if rmErr := os.Remove(indexPath); rmErr != nil {
		fmt.Printf("%s \"%s\": remove indexfile %v\n", change.Path, change.Dest.Id, rmErr)
	}
	return
}

func (g *Commands) remoteMkdirAll(d string) (file *File, err error) {
	// Try the lookup one last time in case a coroutine raced us to it.
	retrFile, retryErr := g.rem.FindByPath(d)
	if retryErr == nil && retrFile != nil {
		return retrFile, nil
	}

	rest, last := remotePathSplit(d)

	parent, parentErr := g.rem.FindByPath(rest)
	if parentErr != nil && parentErr != ErrPathNotExists {
		return parent, parentErr
	}

	if parent == nil {
		parent, parentErr = g.remoteMkdirAll(rest)
		if parentErr != nil || parent == nil {
			return parent, parentErr
		}
	}

	remoteFile := &File{
		IsDir:   true,
		Name:    last,
		ModTime: time.Now(),
	}

	args := upsertOpt{
		parentId: parent.Id,
		src:      remoteFile,
	}
	parent, parentErr = g.rem.UpsertByComparison(&args)
	if parentErr == nil && parent != nil {
		index := parent.ToIndex()
		wErr := g.context.SerializeIndex(index, g.context.AbsPathOf(""))

		// TODO: Should indexing errors be reported?
		if wErr != nil {
			fmt.Printf("serializeIndex %s: %v\n", parent.Name, wErr)
		}
	}
	return parent, parentErr
}

func list(context *config.Context, p string, hidden bool, ignore *regexp.Regexp) (fileChan chan *File, err error) {
	absPath := context.AbsPathOf(p)
	var f []os.FileInfo
	f, err = ioutil.ReadDir(absPath)
	fileChan = make(chan *File)
	if err != nil {
		close(fileChan)
		return
	}

	go func() {
		for _, file := range f {
			if file.Name() == config.GDDirSuffix {
				continue
			}
			if ignore != nil && ignore.Match([]byte(file.Name())) {
				continue
			}
			if !isHidden(file.Name(), hidden) {
				fileChan <- NewLocalFile(gopath.Join(absPath, file.Name()), file)
			}
		}
		close(fileChan)
	}()
	return
}
<|endoftext|>


<commit_before>package integration

import (
	"testing"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/cdn"
	"github.com/stretchr/testify/assert"
)

func TestCdnInstance(t *testing.T) {

	// init client
	config := getConfigFromEnv()
	cdnClient, err := cdn.NewClientWithAccessKey("cn-hangzhou", config.AccessKeyId, config.AccessKeySecret)
	assertErrorNil(t, err, "Failed to init client")
	fmt.Printf("Init client success\n")

	// getCdnStatus
	assertCdnStatus(t, cdnClient)
}

func assertCdnStatus(t *testing.T, client *cdn.Client){
	fmt.Print("describing cdn service status...")
	request := cdn.CreateDescribeCdnServiceRequest()
	response, err := client.DescribeCdnService(request)
	assertErrorNil(t, err, "Failed to describing cdn service status")
	assert.Equal(t, 200, response.GetHttpStatus(), response.GetHttpContentString())
	assert.Equal(t, "PayByTraffic", response.InternetChargeType)
	fmt.Printf("ok(%d)!\n", response.GetHttpStatus())
}
<commit_msg>test key<commit_after>package integration

import (
	"testing"
	"fmt"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/cdn"
	"github.com/stretchr/testify/assert"
	"os"
)

func TestCdnInstance(t *testing.T) {

	// init client
	config := getConfigFromEnv()
	cdnClient, err := cdn.NewClientWithAccessKey("cn-hangzhou", config.AccessKeyId, config.AccessKeySecret)
	assertErrorNil(t, err, "Failed to init client")
	fmt.Printf("Init client success\n")

	// getCdnStatus
	assertCdnStatus(t, cdnClient)

	// test travis if the key is hidden
	testKey := os.Getenv("TestKey")
	fmt.Println("test key : " + testKey)
}

func assertCdnStatus(t *testing.T, client *cdn.Client){
	fmt.Print("describing cdn service status...")
	request := cdn.CreateDescribeCdnServiceRequest()
	response, err := client.DescribeCdnService(request)
	assertErrorNil(t, err, "Failed to describing cdn service status")
	assert.Equal(t, 200, response.GetHttpStatus(), response.GetHttpContentString())
	assert.Equal(t, "PayByTraffic", response.InternetChargeType)
	fmt.Printf("ok(%d)!\n", response.GetHttpStatus())
}
<|endoftext|>


<commit_before>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/nu7hatch/gouuid"
	"github.com/pivotal-golang/lager"
)

const (
	CREATE_ACTION          = "create"
	DELETE_ACTION          = "delete"
	SCALE_ACTION           = "scale"
	DEFAULT_BBS_ADDRESS    = "http://10.244.16.130:8889"
	DEFAULT_SERVER_ID      = "server-1"
	DEFAULT_EXTERNAL_PORT  = 64000
	DEFAULT_CONTAINER_PORT = 5222
)

var (
	logger lager.Logger
)

var serverId = flag.String(
	"serverId",
	DEFAULT_SERVER_ID,
	"ID Of the server being created via Diego",
)

var externalPort = flag.Int(
	"externalPort",
	DEFAULT_EXTERNAL_PORT,
	"The external port.",
)

var containerPort = flag.Int(
	"containerPort",
	DEFAULT_CONTAINER_PORT,
	"The container port.",
)

var bbsAddress = flag.String(
	"bbsAddress",
	DEFAULT_BBS_ADDRESS,
	"URL of diego API",
)

var action = flag.String(
	"action",
	"",
	"The action can be: create, delete or scale.",
)

var processGuid = flag.String(
	"processGuid",
	"",
	"The process GUID of the target LRP.",
)

var numberOfInstances = flag.Int(
	"instances",
	1,
	"The desired number of instances.",
)

type tcpRoute struct {
	ExternalPort  uint16 `json:"external_port"`
	ContainerPort uint16 `json:"container_port"`
}

func main() {
	cf_lager.AddFlags(flag.CommandLine)
	logger, _ = cf_lager.New("desiredlrp-client")

	flag.Parse()

	if *action == "" {
		logger.Fatal("action-required", errors.New("Missing mandatory action parameter"))
	}

	bbsClient := bbs.NewClient(*bbsAddress)

	switch *action {
	case CREATE_ACTION:
		handleCreate(bbsClient)
	case DELETE_ACTION:
		handleDelete(bbsClient)
	case SCALE_ACTION:
		handleScale(bbsClient)
	default:
		logger.Fatal("unknown-parameter", errors.New(fmt.Sprintf("The command [%s] is not valid", *action)))
	}
}

func handleCreate(bbsClient bbs.Client) {
	newProcessGuid, err := uuid.NewV4()
	if err != nil {
		logger.Error("failed-generate-guid", err)
		return
	}
	route := tcpRoute{
		ExternalPort:  uint16(*externalPort),
		ContainerPort: uint16(*containerPort),
	}
	routes := []tcpRoute{route}
	data, err := json.Marshal(routes)
	if err != nil {
		logger.Error("failed-to-marshal", err)
		return
	}
	routingInfo := json.RawMessage(data)
	lrp := models.DesiredLRP{
		ProcessGuid: newProcessGuid.String(),
		LogGuid:     "log-guid",
		Domain:      "ge",
		Instances:   1,
		Setup: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					"curl https://s3.amazonaws.com/router-release-blobs/tcp-sample-receiver.linux -o /tmp/tcp-sample-receiver && chmod +x /tmp/tcp-sample-receiver",
				},
			},
		},
		Action: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					fmt.Sprintf("/tmp/tcp-sample-receiver -address 0.0.0.0:%d -serverId %s", *containerPort, *serverId),
					// fmt.Sprintf("nc -l -k %d > /tmp/output", *containerPort),
				},
			},
		},
		Monitor: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					fmt.Sprintf("nc -z 0.0.0.0 %d", *containerPort),
				},
			},
		},
		StartTimeout: 60,
		RootFs:       "preloaded:cflinuxfs2",
		MemoryMb:     128,
		DiskMb:       128,
		Ports:        []uint32{uint32(*containerPort)},
		Routes: &models.Routes{
			"tcp-router": &routingInfo,
		},
		EgressRules: []*models.SecurityGroupRule{
			&models.SecurityGroupRule{
				Protocol:     "tcp",
				Destinations: []string{"0.0.0.0-255.255.255.255"},
				Ports:        []uint32{80, 443},
			},
			&models.SecurityGroupRule{
				Protocol:     "udp",
				Destinations: []string{"0.0.0.0/0"},
				PortRange: &models.PortRange{
					Start: 53,
					End:   53,
				},
			},
		},
	}
	err = bbsClient.DesireLRP(&lrp)
	if err != nil {
		logger.Error("failed-create", err, lager.Data{"LRP": lrp})
	} else {
		fmt.Printf("Successfully created LRP with process guid %s\n", newProcessGuid)
	}
}

func handleDelete(bbsClient bbs.Client) {
	if *processGuid == "" {
		logger.Fatal("missing-processGuid", errors.New("Missing mandatory processGuid parameter for delete action"))
	}

	err := bbsClient.RemoveDesiredLRP(*processGuid)
	if err != nil {
		logger.Error("failed-to-delete", err, lager.Data{"process-guid": *processGuid})
		return
	}
	fmt.Printf("Desired LRP successfully deleted for process guid %s\n", *processGuid)
}

func handleScale(bbsClient bbs.Client) {
	if *processGuid == "" {
		logger.Fatal("missing-processGuid", errors.New("Missing mandatory processGuid parameter for scale action"))
	}

	instances := int32(*numberOfInstances)
	updatePayload := models.DesiredLRPUpdate{
		Instances: &instances,
	}
	err := bbsClient.UpdateDesiredLRP(*processGuid, &updatePayload)
	if err != nil {
		logger.Error("failed-to-scale", err, lager.Data{"process-guid": *processGuid, "update-request": updatePayload})
		return
	}
	fmt.Printf("LRP %s scaled to number of instances %d\n", *processGuid, *numberOfInstances)
}
<commit_msg>Enhance desired_lrp-client to update tcp routes<commit_after>package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"

	"github.com/cloudfoundry-incubator/bbs"
	"github.com/cloudfoundry-incubator/bbs/models"
	"github.com/cloudfoundry-incubator/cf-lager"
	"github.com/nu7hatch/gouuid"
	"github.com/pivotal-golang/lager"
)

const (
	CREATE_ACTION          = "create"
	UPDATE_ACTION          = "update"
	DELETE_ACTION          = "delete"
	DEFAULT_BBS_ADDRESS    = "http://10.244.16.130:8889"
	DEFAULT_SERVER_ID      = "server-1"
	DEFAULT_EXTERNAL_PORT  = 64000
	DEFAULT_CONTAINER_PORT = 5222
)

var (
	logger lager.Logger
)

var serverId = flag.String(
	"serverId",
	DEFAULT_SERVER_ID,
	"ID Of the server being created via Diego",
)

var externalPort = flag.Int(
	"externalPort",
	0,
	"The external port.",
)

var containerPort = flag.Int(
	"containerPort",
	DEFAULT_CONTAINER_PORT,
	"The container port.",
)

var bbsAddress = flag.String(
	"bbsAddress",
	DEFAULT_BBS_ADDRESS,
	"URL of diego API",
)

var action = flag.String(
	"action",
	"",
	"The action can be: create, delete or scale.",
)

var processGuid = flag.String(
	"processGuid",
	"",
	"The process GUID of the target LRP.",
)

var numberOfInstances = flag.Int(
	"instances",
	-1,
	"The desired number of instances.",
)

type tcpRoute struct {
	ExternalPort  uint16 `json:"external_port"`
	ContainerPort uint16 `json:"container_port"`
}

func main() {
	cf_lager.AddFlags(flag.CommandLine)
	logger, _ = cf_lager.New("desiredlrp-client")

	flag.Parse()

	if *action == "" {
		logger.Fatal("action-required", errors.New("Missing mandatory action parameter"))
	}

	bbsClient := bbs.NewClient(*bbsAddress)

	switch *action {
	case CREATE_ACTION:
		handleCreate(bbsClient)
	case DELETE_ACTION:
		handleDelete(bbsClient)
	case UPDATE_ACTION:
		handleUpdate(bbsClient)
	default:
		logger.Fatal("unknown-parameter", errors.New(fmt.Sprintf("The command [%s] is not valid", *action)))
	}
}

func handleCreate(bbsClient bbs.Client) {
	newProcessGuid, err := uuid.NewV4()
	if err != nil {
		logger.Error("failed-generate-guid", err)
		return
	}
	extPort := *externalPort
	if extPort == 0 {
		extPort = DEFAULT_EXTERNAL_PORT
	}
	route := tcpRoute{
		ExternalPort:  uint16(extPort),
		ContainerPort: uint16(*containerPort),
	}
	routes := []tcpRoute{route}
	data, err := json.Marshal(routes)
	if err != nil {
		logger.Error("failed-to-marshal", err)
		return
	}
	routingInfo := json.RawMessage(data)
	lrp := models.DesiredLRP{
		ProcessGuid: newProcessGuid.String(),
		LogGuid:     "log-guid",
		Domain:      "ge",
		Instances:   1,
		Setup: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					"curl https://s3.amazonaws.com/router-release-blobs/tcp-sample-receiver.linux -o /tmp/tcp-sample-receiver && chmod +x /tmp/tcp-sample-receiver",
				},
			},
		},
		Action: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					fmt.Sprintf("/tmp/tcp-sample-receiver -address 0.0.0.0:%d -serverId %s", *containerPort, *serverId),
					// fmt.Sprintf("nc -l -k %d > /tmp/output", *containerPort),
				},
			},
		},
		Monitor: &models.Action{
			RunAction: &models.RunAction{
				Path: "sh",
				User: "vcap",
				Args: []string{
					"-c",
					fmt.Sprintf("nc -z 0.0.0.0 %d", *containerPort),
				},
			},
		},
		StartTimeout: 60,
		RootFs:       "preloaded:cflinuxfs2",
		MemoryMb:     128,
		DiskMb:       128,
		Ports:        []uint32{uint32(*containerPort)},
		Routes: &models.Routes{
			"tcp-router": &routingInfo,
		},
		EgressRules: []*models.SecurityGroupRule{
			&models.SecurityGroupRule{
				Protocol:     "tcp",
				Destinations: []string{"0.0.0.0-255.255.255.255"},
				Ports:        []uint32{80, 443},
			},
			&models.SecurityGroupRule{
				Protocol:     "udp",
				Destinations: []string{"0.0.0.0/0"},
				PortRange: &models.PortRange{
					Start: 53,
					End:   53,
				},
			},
		},
	}
	err = bbsClient.DesireLRP(&lrp)
	if err != nil {
		logger.Error("failed-create", err, lager.Data{"LRP": lrp})
	} else {
		fmt.Printf("Successfully created LRP with process guid %s\n", newProcessGuid)
	}
}

func handleDelete(bbsClient bbs.Client) {
	if *processGuid == "" {
		logger.Fatal("missing-processGuid", errors.New("Missing mandatory processGuid parameter for delete action"))
	}

	err := bbsClient.RemoveDesiredLRP(*processGuid)
	if err != nil {
		logger.Error("failed-to-delete", err, lager.Data{"process-guid": *processGuid})
		return
	}
	fmt.Printf("Desired LRP successfully deleted for process guid %s\n", *processGuid)
}

func handleUpdate(bbsClient bbs.Client) {
	if *processGuid == "" {
		logger.Fatal("missing-processGuid", errors.New("Missing mandatory processGuid parameter for scale action"))
	}

	updated := false
	var updatePayload models.DesiredLRPUpdate
	if *numberOfInstances >= 0 {
		instances := int32(*numberOfInstances)
		updatePayload.Instances = &instances
		updated = true
	}

	if *externalPort > 0 {
		route := tcpRoute{
			ExternalPort:  uint16(*externalPort),
			ContainerPort: uint16(*containerPort),
		}
		routes := []tcpRoute{route}
		data, err := json.Marshal(routes)
		if err != nil {
			logger.Error("failed-to-marshal", err)
			return
		}
		routingInfo := json.RawMessage(data)
		updatePayload.Routes = &models.Routes{
			"tcp-router": &routingInfo,
		}
		updated = true
	}

	if updated {
		err := bbsClient.UpdateDesiredLRP(*processGuid, &updatePayload)
		if err != nil {
			logger.Error("failed-to-scale", err, lager.Data{"process-guid": *processGuid, "update-request": updatePayload})
			return
		}
		fmt.Printf("LRP %s updated \n", *processGuid)
	}
}
<|endoftext|>


<commit_before><commit_msg>Changed defaults to the so far most successful mode.<commit_after><|endoftext|>


<commit_before>package message

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

	"github.com/koding/bongo"
)

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

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

	// set initial channel id
	req.InitialChannelId = channelId

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

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

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

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

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

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

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

	cm := models.NewChannelMessage()

	conf := config.MustGet()

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

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

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

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

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

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

	return nil
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return cm, nil
}

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

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

	q := request.GetQuery(u)

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

	cmc.AddIsInteracted(q).AddIsFollowed(q)

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

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

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

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

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

	cmc.AddIsInteracted(q).AddIsFollowed(q)

	return response.HandleResultAndError(cmc, cmc.Err)
}
<commit_msg>social: send MessageAdded event via realtime helper<commit_after>package message

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

	"github.com/koding/bongo"
)

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

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

	// set initial channel id
	req.InitialChannelId = channelId

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

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

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

	go realtimehelper.MessageSaved(channelId, req.Id)

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

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

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

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

	cm := models.NewChannelMessage()

	conf := config.MustGet()

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

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

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

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

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

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

	return nil
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	return cm, nil
}

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

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

	q := request.GetQuery(u)

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

	cmc.AddIsInteracted(q).AddIsFollowed(q)

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

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

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

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

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

	cmc.AddIsInteracted(q).AddIsFollowed(q)

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


<commit_before>package apply

import (
	"context"
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
	admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"

	"kubevirt.io/client-go/log"
)

func (r *Reconciler) createOrUpdateValidatingWebhookConfigurations(caBundle []byte) error {

	for _, webhook := range r.targetStrategy.ValidatingWebhookConfigurations() {
		err := r.createOrUpdateValidatingWebhookConfiguration(webhook, caBundle)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *Reconciler) createOrUpdateValidatingWebhookConfiguration(webhook *admissionregistrationv1beta1.ValidatingWebhookConfiguration, caBundle []byte) error {

	version, imageRegistry, id := getTargetVersionRegistryID(r.kv)

	webhook = webhook.DeepCopy()

	for i := range webhook.Webhooks {
		webhook.Webhooks[i].ClientConfig.CABundle = caBundle
	}
	injectOperatorMetadata(r.kv, &webhook.ObjectMeta, version, imageRegistry, id, true)

	var cachedWebhook *admissionregistrationv1beta1.ValidatingWebhookConfiguration
	var err error
	obj, exists, _ := r.stores.ValidationWebhookCache.Get(webhook)
	// since these objects was in the past unmanaged, reconcile and pick it up if it exists

	if !exists {
		cachedWebhook, err = r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Get(context.Background(), webhook.Name, metav1.GetOptions{})
		if errors.IsNotFound(err) {
			exists = false
		} else if err != nil {
			return err
		} else {
			exists = true
		}
	} else {
		cachedWebhook = obj.(*admissionregistrationv1beta1.ValidatingWebhookConfiguration)
	}

	certsMatch := true
	if exists {
		for _, wh := range cachedWebhook.Webhooks {
			if !reflect.DeepEqual(wh.ClientConfig.CABundle, caBundle) {
				certsMatch = false
				break
			}
		}
	}

	if !exists {
		r.expectations.ValidationWebhook.RaiseExpectations(r.kvKey, 1, 0)
		webhook, err := r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(context.Background(), webhook, metav1.CreateOptions{})
		if err != nil {
			r.expectations.ValidationWebhook.LowerExpectations(r.kvKey, 1, 0)
			return fmt.Errorf("unable to create validatingwebhook %+v: %v", webhook, err)
		}
		SetValidatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)

		return nil
	}

	modified := resourcemerge.BoolPtr(false)
	existingCopy := cachedWebhook.DeepCopy()
	expectedGeneration := ExpectedValidatingWebhookConfigurationGeneration(webhook, r.kv.Status.Generations)

	resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, webhook.ObjectMeta)
	// there was no change to metadata, the generation was right
	if !*modified && existingCopy.ObjectMeta.Generation == expectedGeneration && certsMatch {
		log.Log.V(4).Infof("validatingwebhookconfiguration %v is up-to-date", webhook.GetName())
		return nil
	}

	// Patch if old version
	ops := []string{
		fmt.Sprintf(testGenerationJSONPatchTemplate, cachedWebhook.ObjectMeta.Generation),
	}

	// Add Labels and Annotations Patches
	labelAnnotationPatch, err := createLabelsAndAnnotationsPatch(&webhook.ObjectMeta)
	if err != nil {
		return err
	}

	ops = append(ops, labelAnnotationPatch...)

	// Add Spec Patch
	webhooks, err := json.Marshal(webhook.Webhooks)
	if err != nil {
		return err
	}

	ops = append(ops, fmt.Sprintf(replaceWebhooksValueTemplate, string(webhooks)))

	webhook, err = r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Patch(context.Background(), webhook.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
	if err != nil {
		return fmt.Errorf("unable to update validatingwebhookconfiguration %+v: %v", webhook, err)
	}

	SetValidatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)
	log.Log.V(2).Infof("validatingwebhoookconfiguration %v updated", webhook.Name)

	return nil
}

func (r *Reconciler) createOrUpdateMutatingWebhookConfigurations(caBundle []byte) error {
	for _, webhook := range r.targetStrategy.MutatingWebhookConfigurations() {
		err := r.createOrUpdateMutatingWebhookConfiguration(webhook, caBundle)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *Reconciler) createOrUpdateMutatingWebhookConfiguration(webhook *admissionregistrationv1beta1.MutatingWebhookConfiguration, caBundle []byte) error {
	version, imageRegistry, id := getTargetVersionRegistryID(r.kv)

	webhook = webhook.DeepCopy()

	for i := range webhook.Webhooks {
		webhook.Webhooks[i].ClientConfig.CABundle = caBundle
	}

	injectOperatorMetadata(r.kv, &webhook.ObjectMeta, version, imageRegistry, id, true)

	var cachedWebhook *admissionregistrationv1beta1.MutatingWebhookConfiguration
	var err error
	obj, exists, _ := r.stores.MutatingWebhookCache.Get(webhook)
	// since these objects was in the past unmanaged, reconcile and pick it up if it exists
	if !exists {
		cachedWebhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(context.Background(), webhook.Name, metav1.GetOptions{})
		if errors.IsNotFound(err) {
			exists = false
		} else if err != nil {
			return err
		} else {
			exists = true
		}
	} else {
		cachedWebhook = obj.(*admissionregistrationv1beta1.MutatingWebhookConfiguration)
	}

	certsMatch := true
	if exists {
		for _, wh := range cachedWebhook.Webhooks {
			if !reflect.DeepEqual(wh.ClientConfig.CABundle, caBundle) {
				certsMatch = false
				break
			}
		}
	}

	if !exists {
		r.expectations.MutatingWebhook.RaiseExpectations(r.kvKey, 1, 0)
		webhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(context.Background(), webhook, metav1.CreateOptions{})
		if err != nil {
			r.expectations.MutatingWebhook.LowerExpectations(r.kvKey, 1, 0)
			return fmt.Errorf("unable to create mutatingwebhook %+v: %v", webhook, err)
		}

		SetMutatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)

		return nil
	}

	modified := resourcemerge.BoolPtr(false)
	existingCopy := cachedWebhook.DeepCopy()
	expectedGeneration := ExpectedMutatingWebhookConfigurationGeneration(webhook, r.kv.Status.Generations)

	resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, webhook.ObjectMeta)
	// there was no change to metadata, the generation was right
	if !*modified && existingCopy.ObjectMeta.Generation == expectedGeneration && certsMatch {
		log.Log.V(4).Infof("mutating webhook configuration %v is up-to-date", webhook.GetName())
		return nil
	}

	// Patch if old version
	ops := []string{
		fmt.Sprintf(testGenerationJSONPatchTemplate, cachedWebhook.ObjectMeta.Generation),
	}

	// Add Labels and Annotations Patches
	labelAnnotationPatch, err := createLabelsAndAnnotationsPatch(&webhook.ObjectMeta)
	if err != nil {
		return err
	}
	ops = append(ops, labelAnnotationPatch...)

	// Add Spec Patch
	webhooks, err := json.Marshal(webhook.Webhooks)
	if err != nil {
		return err
	}

	ops = append(ops, fmt.Sprintf(replaceWebhooksValueTemplate, string(webhooks)))

	webhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Patch(context.Background(), webhook.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
	if err != nil {
		return fmt.Errorf("unable to update mutatingwebhookconfiguration %+v: %v", webhook, err)
	}

	SetMutatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)
	log.Log.V(2).Infof("mutatingwebhoookconfiguration %v updated", webhook.Name)

	return nil
}
<commit_msg>Update pkg/virt-operator/resource/apply/admissionregistration.go<commit_after>package apply

import (
	"context"
	"encoding/json"
	"fmt"
	"reflect"

	"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
	admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
	"k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"

	"kubevirt.io/client-go/log"
)

func (r *Reconciler) createOrUpdateValidatingWebhookConfigurations(caBundle []byte) error {

	for _, webhook := range r.targetStrategy.ValidatingWebhookConfigurations() {
		err := r.createOrUpdateValidatingWebhookConfiguration(webhook, caBundle)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *Reconciler) createOrUpdateValidatingWebhookConfiguration(webhook *admissionregistrationv1beta1.ValidatingWebhookConfiguration, caBundle []byte) error {

	version, imageRegistry, id := getTargetVersionRegistryID(r.kv)

	webhook = webhook.DeepCopy()

	for i := range webhook.Webhooks {
		webhook.Webhooks[i].ClientConfig.CABundle = caBundle
	}
	injectOperatorMetadata(r.kv, &webhook.ObjectMeta, version, imageRegistry, id, true)

	var cachedWebhook *admissionregistrationv1beta1.ValidatingWebhookConfiguration
	var err error
	obj, exists, _ := r.stores.ValidationWebhookCache.Get(webhook)
	// since these objects was in the past unmanaged, reconcile and pick it up if it exists

	if !exists {
		cachedWebhook, err = r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Get(context.Background(), webhook.Name, metav1.GetOptions{})
		if errors.IsNotFound(err) {
			exists = false
		} else if err != nil {
			return err
		} else {
			exists = true
		}
	} else {
		cachedWebhook = obj.(*admissionregistrationv1beta1.ValidatingWebhookConfiguration)
	}

	certsMatch := true
	if exists {
		for _, wh := range cachedWebhook.Webhooks {
			if !reflect.DeepEqual(wh.ClientConfig.CABundle, caBundle) {
				certsMatch = false
				break
			}
		}
	}

	if !exists {
		r.expectations.ValidationWebhook.RaiseExpectations(r.kvKey, 1, 0)
		webhook, err := r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Create(context.Background(), webhook, metav1.CreateOptions{})
		if err != nil {
			r.expectations.ValidationWebhook.LowerExpectations(r.kvKey, 1, 0)
			return fmt.Errorf("unable to create validatingwebhook %+v: %v", webhook, err)
		}
		SetValidatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)

		return nil
	}

	modified := resourcemerge.BoolPtr(false)
	existingCopy := cachedWebhook.DeepCopy()
	expectedGeneration := ExpectedValidatingWebhookConfigurationGeneration(webhook, r.kv.Status.Generations)

	resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, webhook.ObjectMeta)
	// there was no change to metadata, the generation was right
	if !*modified && existingCopy.ObjectMeta.Generation == expectedGeneration && certsMatch {
		log.Log.V(4).Infof("validatingwebhookconfiguration %v is up-to-date", webhook.GetName())
		return nil
	}

	// Patch if old version
	ops := []string{
		fmt.Sprintf(testGenerationJSONPatchTemplate, cachedWebhook.ObjectMeta.Generation),
	}

	// Add Labels and Annotations Patches
	labelAnnotationPatch, err := createLabelsAndAnnotationsPatch(&webhook.ObjectMeta)
	if err != nil {
		return err
	}

	ops = append(ops, labelAnnotationPatch...)

	// Add Spec Patch
	webhooks, err := json.Marshal(webhook.Webhooks)
	if err != nil {
		return err
	}

	ops = append(ops, fmt.Sprintf(replaceWebhooksValueTemplate, string(webhooks)))

	webhook, err = r.clientset.AdmissionregistrationV1beta1().ValidatingWebhookConfigurations().Patch(context.Background(), webhook.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
	if err != nil {
		return fmt.Errorf("unable to update validatingwebhookconfiguration %+v: %v", webhook, err)
	}

	SetValidatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)
	log.Log.V(2).Infof("validatingwebhoookconfiguration %v updated", webhook.Name)

	return nil
}

func (r *Reconciler) createOrUpdateMutatingWebhookConfigurations(caBundle []byte) error {
	for _, webhook := range r.targetStrategy.MutatingWebhookConfigurations() {
		err := r.createOrUpdateMutatingWebhookConfiguration(webhook, caBundle)
		if err != nil {
			return err
		}
	}

	return nil
}

func (r *Reconciler) createOrUpdateMutatingWebhookConfiguration(webhook *admissionregistrationv1beta1.MutatingWebhookConfiguration, caBundle []byte) error {
	version, imageRegistry, id := getTargetVersionRegistryID(r.kv)

	webhook = webhook.DeepCopy()

	for i := range webhook.Webhooks {
		webhook.Webhooks[i].ClientConfig.CABundle = caBundle
	}

	injectOperatorMetadata(r.kv, &webhook.ObjectMeta, version, imageRegistry, id, true)

	var cachedWebhook *admissionregistrationv1beta1.MutatingWebhookConfiguration
	var err error
	obj, exists, _ := r.stores.MutatingWebhookCache.Get(webhook)
	// since these objects was in the past unmanaged, reconcile and pick it up if it exists
	if !exists {
		cachedWebhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Get(context.Background(), webhook.Name, metav1.GetOptions{})
		if errors.IsNotFound(err) {
			exists = false
		} else if err != nil {
			return err
		} else {
			exists = true
		}
	} else {
		cachedWebhook = obj.(*admissionregistrationv1beta1.MutatingWebhookConfiguration)
	}

	certsMatch := true
	if exists {
		for _, wh := range cachedWebhook.Webhooks {
			if !reflect.DeepEqual(wh.ClientConfig.CABundle, caBundle) {
				certsMatch = false
				break
			}
		}
	}

	if !exists {
		r.expectations.MutatingWebhook.RaiseExpectations(r.kvKey, 1, 0)
		webhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Create(context.Background(), webhook, metav1.CreateOptions{})
		if err != nil {
			r.expectations.MutatingWebhook.LowerExpectations(r.kvKey, 1, 0)
			return fmt.Errorf("unable to create mutatingwebhook %+v: %v", webhook, err)
		}

		SetMutatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)
		log.Log.V(2).Infof("mutatingwebhoookconfiguration %v created", webhook.Name)
		return nil
	}

	modified := resourcemerge.BoolPtr(false)
	existingCopy := cachedWebhook.DeepCopy()
	expectedGeneration := ExpectedMutatingWebhookConfigurationGeneration(webhook, r.kv.Status.Generations)

	resourcemerge.EnsureObjectMeta(modified, &existingCopy.ObjectMeta, webhook.ObjectMeta)
	// there was no change to metadata, the generation was right
	if !*modified && existingCopy.ObjectMeta.Generation == expectedGeneration && certsMatch {
		log.Log.V(4).Infof("mutating webhook configuration %v is up-to-date", webhook.GetName())
		return nil
	}

	// Patch if old version
	ops := []string{
		fmt.Sprintf(testGenerationJSONPatchTemplate, cachedWebhook.ObjectMeta.Generation),
	}

	// Add Labels and Annotations Patches
	labelAnnotationPatch, err := createLabelsAndAnnotationsPatch(&webhook.ObjectMeta)
	if err != nil {
		return err
	}
	ops = append(ops, labelAnnotationPatch...)

	// Add Spec Patch
	webhooks, err := json.Marshal(webhook.Webhooks)
	if err != nil {
		return err
	}

	ops = append(ops, fmt.Sprintf(replaceWebhooksValueTemplate, string(webhooks)))

	webhook, err = r.clientset.AdmissionregistrationV1beta1().MutatingWebhookConfigurations().Patch(context.Background(), webhook.Name, types.JSONPatchType, generatePatchBytes(ops), metav1.PatchOptions{})
	if err != nil {
		return fmt.Errorf("unable to update mutatingwebhookconfiguration %+v: %v", webhook, err)
	}

	SetMutatingWebhookConfigurationGeneration(&r.kv.Status.Generations, webhook)
	log.Log.V(2).Infof("mutatingwebhoookconfiguration %v updated", webhook.Name)

	return nil
}
<|endoftext|>