<commit_before>package sessiontest

import (
	"encoding/base64"
	"encoding/json"
	"github.com/privacybydesign/irmago/server/requestorserver"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	irma "github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/internal/common"
	"github.com/privacybydesign/irmago/internal/test"
	"github.com/privacybydesign/irmago/irmaclient"
	"github.com/privacybydesign/irmago/server"
	"github.com/stretchr/testify/require"
)

func TestMain(m *testing.M) {
	// Create HTTP server for scheme managers
	test.StartSchemeManagerHttpServer()

	retval := m.Run()

	test.StopSchemeManagerHttpServer()
	test.ClearAllTestStorage()

	os.Exit(retval)
}

func parseStorage(t *testing.T) (*irmaclient.Client, *TestClientHandler) {
	storage := test.SetupTestStorage(t)
	return parseExistingStorage(t, storage)
}

func parseExistingStorage(t *testing.T, storage string) (*irmaclient.Client, *TestClientHandler) {
	handler := &TestClientHandler{t: t, c: make(chan error), storage: storage}
	path := test.FindTestdataFolder(t)
	client, err := irmaclient.New(
		filepath.Join(storage, "client"),
		filepath.Join(path, "irma_configuration"),
		handler,
	)
	require.NoError(t, err)
	client.SetPreferences(irmaclient.Preferences{DeveloperMode: true})
	return client, handler
}

func getDisclosureRequest(id irma.AttributeTypeIdentifier) *irma.DisclosureRequest {
	return irma.NewDisclosureRequest(id)
}

func getSigningRequest(id irma.AttributeTypeIdentifier) *irma.SignatureRequest {
	return irma.NewSignatureRequest("test", id)
}

func getIssuanceRequest(defaultValidity bool) *irma.IssuanceRequest {
	temp := irma.Timestamp(irma.FloorToEpochBoundary(time.Now().AddDate(1, 0, 0)))
	var expiry *irma.Timestamp
	if !defaultValidity {
		expiry = &temp
	}
	return irma.NewIssuanceRequest([]*irma.CredentialRequest{
		{
			Validity:         expiry,
			CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.RU.studentCard"),
			Attributes: map[string]string{
				"university":        "Radboud",
				"studentCardNumber": "31415927",
				"studentID":         "s1234567",
				"level":             "42",
			},
		},
	})
}

func getNameIssuanceRequest() *irma.IssuanceRequest {
	expiry := irma.Timestamp(irma.NewMetadataAttribute(0).Expiry())
	return irma.NewIssuanceRequest([]*irma.CredentialRequest{
		{
			Validity:         &expiry,
			CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
			Attributes: map[string]string{
				"firstnames": "Johan Pieter",
				"firstname":  "Johan",
				"familyname": "Stuivezand",
			},
		},
	})

}

func getSpecialIssuanceRequest(defaultValidity bool, attribute string) *irma.IssuanceRequest {
	request := getIssuanceRequest(defaultValidity)
	request.Credentials[0].Attributes["studentCardNumber"] = attribute
	return request
}

func getCombinedIssuanceRequest(id irma.AttributeTypeIdentifier) *irma.IssuanceRequest {
	request := getIssuanceRequest(false)
	request.AddSingle(id, nil, nil)
	return request
}

func getMultipleIssuanceRequest() *irma.IssuanceRequest {
	request := getIssuanceRequest(false)
	request.Credentials = append(request.Credentials, &irma.CredentialRequest{
		Validity:         request.Credentials[0].Validity,
		CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
		Attributes: map[string]string{
			"firstnames": "Johan Pieter",
			"firstname":  "Johan",
			"familyname": "Stuivezand",
		},
	})
	return request
}

func startSession(t *testing.T, request irma.SessionRequest, sessiontype string, useJWTs bool) *server.SessionPackage {
	var (
		sesPkg server.SessionPackage
		err    error
	)

	url := "http://localhost:48682"
	if useJWTs {
		err = irma.NewHTTPTransport(url, false).Post("session", &sesPkg, getJwt(t, request, sessiontype, jwt.SigningMethodRS256))
	} else {
		err = irma.NewHTTPTransport(url, false).Post("session", &sesPkg, request)
	}

	require.NoError(t, err)
	return &sesPkg
}

func getJwt(t *testing.T, request irma.SessionRequest, sessiontype string, alg jwt.SigningMethod) string {
	var jwtcontents irma.RequestorJwt
	var kid string
	switch sessiontype {
	case "issue":
		kid = "testip"
		jwtcontents = irma.NewIdentityProviderJwt("testip", request.(*irma.IssuanceRequest))
	case "verification":
		kid = "testsp"
		jwtcontents = irma.NewServiceProviderJwt("testsp", request.(*irma.DisclosureRequest))
	case "signature":
		kid = "testsigclient"
		jwtcontents = irma.NewSignatureRequestorJwt("testsigclient", request.(*irma.SignatureRequest))
	}

	var j string
	var err error

	switch alg {
	case jwt.SigningMethodRS256:
		skbts, err := ioutil.ReadFile(filepath.Join(test.FindTestdataFolder(t), "jwtkeys", "requestor1-sk.pem"))
		require.NoError(t, err)
		sk, err := jwt.ParseRSAPrivateKeyFromPEM(skbts)
		require.NoError(t, err)
		tok := jwt.NewWithClaims(jwt.SigningMethodRS256, jwtcontents)
		tok.Header["kid"] = "requestor1"
		j, err = tok.SignedString(sk)
		require.NoError(t, err)
	case jwt.SigningMethodHS256:
		tok := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtcontents)
		tok.Header["kid"] = "requestor3"
		bts, err := base64.StdEncoding.DecodeString(JwtServerConfiguration().Requestors["requestor3"].AuthenticationKey)
		require.NoError(t, err)
		j, err = tok.SignedString(bts)
		require.NoError(t, err)
	case jwt.SigningMethodNone:
		tok := jwt.NewWithClaims(jwt.SigningMethodNone, jwtcontents)
		tok.Header["kid"] = kid
		j, err = tok.SignedString(jwt.UnsafeAllowNoneSignatureType)
		require.NoError(t, err)
	}

	return j
}

func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client) string {
	return sessionHelperWithConfig(t, request, sessiontype, client, JwtServerConfiguration())
}

func sessionHelperWithConfig(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client, config *requestorserver.Configuration) string {
	if client == nil {
		var handler *TestClientHandler
		client, handler = parseStorage(t)
		defer test.ClearTestStorage(t, handler.storage)
	}

	authEnabled := false
	if config != nil {
		authEnabled = !config.DisableRequestorAuthentication // TODO: refactor test configuration so authentication method can easily be specified in test
		rs := StartRequestorServer(t, config)
		defer rs.Stop()
	}

	sesPkg := startSession(t, request, sessiontype, authEnabled)

	c := make(chan *SessionResult)
	h := &TestHandler{t: t, c: c, client: client, expectedServerName: expectedRequestorInfo(t, client.Configuration)}
	qrjson, err := json.Marshal(sesPkg.SessionPtr)
	require.NoError(t, err)
	client.NewSession(string(qrjson), h)

	if result := <-c; result != nil {
		require.NoError(t, result.Err)
	}

	resultEndpoint := "result"
	if authEnabled {
		resultEndpoint = "result-jwt"
	}

	var res string
	err = irma.NewHTTPTransport("http://localhost:48682/session/"+sesPkg.Token, false).Get(resultEndpoint, &res)
	require.NoError(t, err)

	return res
}

func expectedRequestorInfo(t *testing.T, conf *irma.Configuration) *irma.RequestorInfo {
	if common.ForceHTTPS {
		return irma.NewRequestorInfo("localhost")
	}
	require.Contains(t, conf.Requestors, "localhost")
	return conf.Requestors["localhost"]
}
<commit_msg>docs: add comment to explain hacky solution nin test file.<commit_after>package sessiontest

import (
	"encoding/base64"
	"encoding/json"
	"github.com/privacybydesign/irmago/server/requestorserver"
	"io/ioutil"
	"os"
	"path/filepath"
	"testing"
	"time"

	jwt "github.com/dgrijalva/jwt-go"
	irma "github.com/privacybydesign/irmago"
	"github.com/privacybydesign/irmago/internal/common"
	"github.com/privacybydesign/irmago/internal/test"
	"github.com/privacybydesign/irmago/irmaclient"
	"github.com/privacybydesign/irmago/server"
	"github.com/stretchr/testify/require"
)

func TestMain(m *testing.M) {
	// Create HTTP server for scheme managers
	test.StartSchemeManagerHttpServer()

	retval := m.Run()

	test.StopSchemeManagerHttpServer()
	test.ClearAllTestStorage()

	os.Exit(retval)
}

func parseStorage(t *testing.T) (*irmaclient.Client, *TestClientHandler) {
	storage := test.SetupTestStorage(t)
	return parseExistingStorage(t, storage)
}

func parseExistingStorage(t *testing.T, storage string) (*irmaclient.Client, *TestClientHandler) {
	handler := &TestClientHandler{t: t, c: make(chan error), storage: storage}
	path := test.FindTestdataFolder(t)
	client, err := irmaclient.New(
		filepath.Join(storage, "client"),
		filepath.Join(path, "irma_configuration"),
		handler,
	)
	require.NoError(t, err)
	client.SetPreferences(irmaclient.Preferences{DeveloperMode: true})
	return client, handler
}

func getDisclosureRequest(id irma.AttributeTypeIdentifier) *irma.DisclosureRequest {
	return irma.NewDisclosureRequest(id)
}

func getSigningRequest(id irma.AttributeTypeIdentifier) *irma.SignatureRequest {
	return irma.NewSignatureRequest("test", id)
}

func getIssuanceRequest(defaultValidity bool) *irma.IssuanceRequest {
	temp := irma.Timestamp(irma.FloorToEpochBoundary(time.Now().AddDate(1, 0, 0)))
	var expiry *irma.Timestamp
	if !defaultValidity {
		expiry = &temp
	}
	return irma.NewIssuanceRequest([]*irma.CredentialRequest{
		{
			Validity:         expiry,
			CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.RU.studentCard"),
			Attributes: map[string]string{
				"university":        "Radboud",
				"studentCardNumber": "31415927",
				"studentID":         "s1234567",
				"level":             "42",
			},
		},
	})
}

func getNameIssuanceRequest() *irma.IssuanceRequest {
	expiry := irma.Timestamp(irma.NewMetadataAttribute(0).Expiry())
	return irma.NewIssuanceRequest([]*irma.CredentialRequest{
		{
			Validity:         &expiry,
			CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
			Attributes: map[string]string{
				"firstnames": "Johan Pieter",
				"firstname":  "Johan",
				"familyname": "Stuivezand",
			},
		},
	})

}

func getSpecialIssuanceRequest(defaultValidity bool, attribute string) *irma.IssuanceRequest {
	request := getIssuanceRequest(defaultValidity)
	request.Credentials[0].Attributes["studentCardNumber"] = attribute
	return request
}

func getCombinedIssuanceRequest(id irma.AttributeTypeIdentifier) *irma.IssuanceRequest {
	request := getIssuanceRequest(false)
	request.AddSingle(id, nil, nil)
	return request
}

func getMultipleIssuanceRequest() *irma.IssuanceRequest {
	request := getIssuanceRequest(false)
	request.Credentials = append(request.Credentials, &irma.CredentialRequest{
		Validity:         request.Credentials[0].Validity,
		CredentialTypeID: irma.NewCredentialTypeIdentifier("irma-demo.MijnOverheid.fullName"),
		Attributes: map[string]string{
			"firstnames": "Johan Pieter",
			"firstname":  "Johan",
			"familyname": "Stuivezand",
		},
	})
	return request
}

func startSession(t *testing.T, request irma.SessionRequest, sessiontype string, useJWTs bool) *server.SessionPackage {
	var (
		sesPkg server.SessionPackage
		err    error
	)

	url := "http://localhost:48682"
	if useJWTs {
		err = irma.NewHTTPTransport(url, false).Post("session", &sesPkg, getJwt(t, request, sessiontype, jwt.SigningMethodRS256))
	} else {
		err = irma.NewHTTPTransport(url, false).Post("session", &sesPkg, request)
	}

	require.NoError(t, err)
	return &sesPkg
}

func getJwt(t *testing.T, request irma.SessionRequest, sessiontype string, alg jwt.SigningMethod) string {
	var jwtcontents irma.RequestorJwt
	var kid string
	switch sessiontype {
	case "issue":
		kid = "testip"
		jwtcontents = irma.NewIdentityProviderJwt("testip", request.(*irma.IssuanceRequest))
	case "verification":
		kid = "testsp"
		jwtcontents = irma.NewServiceProviderJwt("testsp", request.(*irma.DisclosureRequest))
	case "signature":
		kid = "testsigclient"
		jwtcontents = irma.NewSignatureRequestorJwt("testsigclient", request.(*irma.SignatureRequest))
	}

	var j string
	var err error

	switch alg {
	case jwt.SigningMethodRS256:
		skbts, err := ioutil.ReadFile(filepath.Join(test.FindTestdataFolder(t), "jwtkeys", "requestor1-sk.pem"))
		require.NoError(t, err)
		sk, err := jwt.ParseRSAPrivateKeyFromPEM(skbts)
		require.NoError(t, err)
		tok := jwt.NewWithClaims(jwt.SigningMethodRS256, jwtcontents)
		tok.Header["kid"] = "requestor1"
		j, err = tok.SignedString(sk)
		require.NoError(t, err)
	case jwt.SigningMethodHS256:
		tok := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtcontents)
		tok.Header["kid"] = "requestor3"
		bts, err := base64.StdEncoding.DecodeString(JwtServerConfiguration().Requestors["requestor3"].AuthenticationKey)
		require.NoError(t, err)
		j, err = tok.SignedString(bts)
		require.NoError(t, err)
	case jwt.SigningMethodNone:
		tok := jwt.NewWithClaims(jwt.SigningMethodNone, jwtcontents)
		tok.Header["kid"] = kid
		j, err = tok.SignedString(jwt.UnsafeAllowNoneSignatureType)
		require.NoError(t, err)
	}

	return j
}

func sessionHelper(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client) string {
	return sessionHelperWithConfig(t, request, sessiontype, client, JwtServerConfiguration())
}

func sessionHelperWithConfig(t *testing.T, request irma.SessionRequest, sessiontype string, client *irmaclient.Client, config *requestorserver.Configuration) string {
	if client == nil {
		var handler *TestClientHandler
		client, handler = parseStorage(t)
		defer test.ClearTestStorage(t, handler.storage)
	}

	authEnabled := false
	if config != nil {
		authEnabled = !config.DisableRequestorAuthentication // TODO: refactor test configuration so authentication method can easily be specified in test
		rs := StartRequestorServer(t, config)
		defer rs.Stop()
	}

	sesPkg := startSession(t, request, sessiontype, authEnabled)

	c := make(chan *SessionResult)
	h := &TestHandler{t: t, c: c, client: client, expectedServerName: expectedRequestorInfo(t, client.Configuration)}
	qrjson, err := json.Marshal(sesPkg.SessionPtr)
	require.NoError(t, err)
	client.NewSession(string(qrjson), h)

	if result := <-c; result != nil {
		require.NoError(t, result.Err)
	}

	// hacky solution since all tests that require JWT signing also test requestor authentication, see TODO above
	resultEndpoint := "result"
	if authEnabled {
		resultEndpoint = "result-jwt"
	}

	var res string
	err = irma.NewHTTPTransport("http://localhost:48682/session/"+sesPkg.Token, false).Get(resultEndpoint, &res)
	require.NoError(t, err)

	return res
}

func expectedRequestorInfo(t *testing.T, conf *irma.Configuration) *irma.RequestorInfo {
	if common.ForceHTTPS {
		return irma.NewRequestorInfo("localhost")
	}
	require.Contains(t, conf.Requestors, "localhost")
	return conf.Requestors["localhost"]
}
<|endoftext|>


<commit_before>// Copyright 2022 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.

// For now, we are not writing the unit test, which requires multiple
// version of same object. As this is not supported by fake-storage-server.
// Although API is exposed to enable the object versioning for a bucket,
// but it returns "method not allowed" when we call it.

package storage

import (
	"fmt"
	"io"

	"cloud.google.com/go/storage"
	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

type bucketHandle struct {
	gcs.Bucket
	bucket *storage.BucketHandle
}

func (bh *bucketHandle) NewReader(
	ctx context.Context,
	req *gcs.ReadObjectRequest) (rc io.ReadCloser, err error) {
	// Initialising the starting offset and the length to be read by the reader.
	start := int64((*req.Range).Start)
	end := int64((*req.Range).Limit)
	length := int64(end - start)

	obj := bh.bucket.Object(req.Name)

	// Switching to the requested generation of object.
	if req.Generation != 0 {
		obj = obj.Generation(req.Generation)
	}

	// Creating a NewRangeReader instance.
	r, err := obj.NewRangeReader(ctx, start, length)
	if err != nil {
		err = fmt.Errorf("error in creating a NewRangeReader instance: %v", err)
		return
	}

	// Converting io.Reader to io.ReadCloser by adding a no-op closer method
	// to match the return type interface.
	rc = io.NopCloser(r)
	return
}
func (b *bucketHandle) DeleteObject(ctx context.Context, req *gcs.DeleteObjectRequest) (err error) {
	obj := b.bucket.Object(req.Name)

	// Switching to the requested generation of the object.
	if req.Generation != 0 {
		obj = obj.Generation(req.Generation)
	}
	// Putting condition that the object's MetaGeneration should match the requested MetaGeneration for deletion to occur.
	if req.MetaGenerationPrecondition != nil && *req.MetaGenerationPrecondition != 0 {
		obj = obj.If(storage.Conditions{MetagenerationMatch: *req.MetaGenerationPrecondition})
	}

	// Deleting object through Go Storage Client.
	err = obj.Delete(ctx)

	return
}
<commit_msg>delete object method and unit test<commit_after>// Copyright 2022 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.

// For now, we are not writing the unit test, which requires multiple
// version of same object. As this is not supported by fake-storage-server.
// Although API is exposed to enable the object versioning for a bucket,
// but it returns "method not allowed" when we call it.

package storage

import (
	"fmt"
	"io"

	"cloud.google.com/go/storage"
	"github.com/jacobsa/gcloud/gcs"
	"golang.org/x/net/context"
)

type bucketHandle struct {
	gcs.Bucket
	bucket *storage.BucketHandle
}

func (bh *bucketHandle) NewReader(
	ctx context.Context,
	req *gcs.ReadObjectRequest) (rc io.ReadCloser, err error) {
	// Initialising the starting offset and the length to be read by the reader.
	start := int64((*req.Range).Start)
	end := int64((*req.Range).Limit)
	length := int64(end - start)

	obj := bh.bucket.Object(req.Name)

	// Switching to the requested generation of object.
	if req.Generation != 0 {
		obj = obj.Generation(req.Generation)
	}

	// Creating a NewRangeReader instance.
	r, err := obj.NewRangeReader(ctx, start, length)
	if err != nil {
		err = fmt.Errorf("error in creating a NewRangeReader instance: %v", err)
		return
	}

	// Converting io.Reader to io.ReadCloser by adding a no-op closer method
	// to match the return type interface.
	rc = io.NopCloser(r)
	return
}
func (b *bucketHandle) DeleteObject(ctx context.Context, req *gcs.DeleteObjectRequest) (err error) {
	obj := b.bucket.Object(req.Name)

	// Switching to the requested generation of the object.
	if req.Generation != 0 {
		obj = obj.Generation(req.Generation)
	}
	// Putting condition that the object's MetaGeneration should match the requested MetaGeneration for deletion to occur.
	if req.MetaGenerationPrecondition != nil && *req.MetaGenerationPrecondition != 0 {
		obj = obj.If(storage.Conditions{MetagenerationMatch: *req.MetaGenerationPrecondition})
	}

	// Deleting object through Go Storage Client.
	return obj.Delete(ctx)
}
<|endoftext|>


<commit_before>package builder

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"sort"

	"github.com/Symantec/Dominator/lib/format"
)

func (b *Builder) writeHtml(writer io.Writer) {
	fmt.Fprintf(writer,
		"Number of image streams: %d
\n",
		b.getNumNormalStreams())
	currentBuilds := make([]string, 0)
	goodBuilds := make(map[string]buildResultType)
	failedBuilds := make(map[string]buildResultType)
	b.buildResultsLock.RLock()
	for name := range b.currentBuildLogs {
		currentBuilds = append(currentBuilds, name)
	}
	for name, result := range b.lastBuildResults {
		if result.error == nil {
			goodBuilds[name] = result
		} else {
			failedBuilds[name] = result
		}
	}
	b.buildResultsLock.RUnlock()
	if len(currentBuilds) > 0 {
		fmt.Fprintln(writer, "Current image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range currentBuilds {
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
	if len(failedBuilds) > 0 {
		streamNames := make([]string, 0, len(failedBuilds))
		for streamName := range failedBuilds {
			streamNames = append(streamNames, streamName)
		}
		sort.Strings(streamNames)
		fmt.Fprintln(writer, "Failed image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Error	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range streamNames {
			result := failedBuilds[streamName]
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer, "    %s	\n", result.error)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
	if len(goodBuilds) > 0 {
		streamNames := make([]string, 0, len(goodBuilds))
		for streamName := range goodBuilds {
			streamNames = append(streamNames, streamName)
		}
		sort.Strings(streamNames)
		fmt.Fprintln(writer, "Successful image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Name	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range streamNames {
			result := goodBuilds[streamName]
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer,
				"    %s	\n",
				b.imageServerAddress, result.imageName, result.imageName)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
}

func (b *Builder) showImageStream(writer io.Writer, streamName string) {
	stream := b.getNormalStream(streamName)
	if stream == nil {
		fmt.Fprintf(writer, "Stream: %s does not exist!\n", streamName)
		return
	}
	fmt.Fprintf(writer, "
Information for stream: %s
\n", streamName)
	fmt.Fprintf(writer, "Manifest URL: %s
\n",
		stream.ManifestUrl)
	fmt.Fprintf(writer, "Manifest Directory: %s
\n",
		stream.ManifestDirectory)
	manifestDirectory, err := stream.getManifest(b, streamName, "",
		new(bytes.Buffer))
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	defer os.RemoveAll(manifestDirectory)
	manifestFilename := path.Join(manifestDirectory, "manifest")
	manifestBytes, err := ioutil.ReadFile(manifestFilename)
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	var manifest manifestType
	if err := json.Unmarshal(manifestBytes, &manifest); err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	sourceStream := b.getNormalStream(manifest.SourceImage)
	if sourceStream == nil {
		fmt.Fprintf(writer, "SourceImage: %s
\n",
			manifest.SourceImage)
	} else {
		fmt.Fprintf(writer,
			"SourceImage: %s
\n",
			manifest.SourceImage, manifest.SourceImage)
	}
	fmt.Fprintln(writer, "Contents of manifest file:
")
	fmt.Fprintln(writer, "
")
	writer.Write(manifestBytes)
	fmt.Fprintln(writer, "

")
	packagesFile, err := os.Open(path.Join(manifestDirectory, "package-list"))
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	defer packagesFile.Close()
	fmt.Fprintln(writer, "Contents of package-list file:
")
	fmt.Fprintln(writer, "
")
	io.Copy(writer, packagesFile)
	fmt.Fprintln(writer, "

")
	if size, err := getTreeSize(manifestDirectory); err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	} else {
		fmt.Fprintf(writer, "Manifest tree size: %s
\n",
			format.FormatBytes(size))
	}
}

func (b *Builder) showImageStreams(writer io.Writer) {
	streamNames := b.listNormalStreamNames()
	sort.Strings(streamNames)
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Image Stream	")
	fmt.Fprintln(writer, "    ManifestUrl	")
	fmt.Fprintln(writer, "    ManifestDirectory	")
	fmt.Fprintln(writer, "
")
	for _, streamName := range streamNames {
		imageStream := b.getNormalStream(streamName)
		if imageStream == nil {
			continue
		}
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer,
			"    %s	\n",
			streamName, streamName)
		fmt.Fprintf(writer, "    %s	\n", imageStream.ManifestUrl)
		fmt.Fprintf(writer, "    %s	\n", imageStream.ManifestDirectory)
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
}
<commit_msg>Show logs, prettify code segments when showing image stream in imaginator.<commit_after>package builder

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path"
	"sort"

	"github.com/Symantec/Dominator/lib/format"
)

const codeStyle = `background-color: #eee; border: 1px solid #999; display: block; float: left;`

func (b *Builder) writeHtml(writer io.Writer) {
	fmt.Fprintf(writer,
		"Number of image streams: %d
\n",
		b.getNumNormalStreams())
	currentBuilds := make([]string, 0)
	goodBuilds := make(map[string]buildResultType)
	failedBuilds := make(map[string]buildResultType)
	b.buildResultsLock.RLock()
	for name := range b.currentBuildLogs {
		currentBuilds = append(currentBuilds, name)
	}
	for name, result := range b.lastBuildResults {
		if result.error == nil {
			goodBuilds[name] = result
		} else {
			failedBuilds[name] = result
		}
	}
	b.buildResultsLock.RUnlock()
	if len(currentBuilds) > 0 {
		fmt.Fprintln(writer, "Current image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range currentBuilds {
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
	if len(failedBuilds) > 0 {
		streamNames := make([]string, 0, len(failedBuilds))
		for streamName := range failedBuilds {
			streamNames = append(streamNames, streamName)
		}
		sort.Strings(streamNames)
		fmt.Fprintln(writer, "Failed image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Error	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range streamNames {
			result := failedBuilds[streamName]
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer, "    %s	\n", result.error)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
	if len(goodBuilds) > 0 {
		streamNames := make([]string, 0, len(goodBuilds))
		for streamName := range goodBuilds {
			streamNames = append(streamNames, streamName)
		}
		sort.Strings(streamNames)
		fmt.Fprintln(writer, "Successful image builds:
")
		fmt.Fprintln(writer, `<table border="1">`)
		fmt.Fprintln(writer, "
")
		fmt.Fprintln(writer, "    Image Stream	")
		fmt.Fprintln(writer, "    Name	")
		fmt.Fprintln(writer, "    Build log	")
		fmt.Fprintln(writer, "
")
		for _, streamName := range streamNames {
			result := goodBuilds[streamName]
			fmt.Fprintf(writer, "
\n")
			fmt.Fprintf(writer, "    %s	\n", streamName)
			fmt.Fprintf(writer,
				"    %s	\n",
				b.imageServerAddress, result.imageName, result.imageName)
			fmt.Fprintf(writer,
				"    log	\n",
				streamName)
			fmt.Fprintf(writer, "
\n")
		}
		fmt.Fprintln(writer, "

")
	}
}

func (b *Builder) showImageStream(writer io.Writer, streamName string) {
	stream := b.getNormalStream(streamName)
	if stream == nil {
		fmt.Fprintf(writer, "Stream: %s does not exist!\n", streamName)
		return
	}
	fmt.Fprintf(writer, "
Information for stream: %s
\n", streamName)
	fmt.Fprintf(writer, "Manifest URL: %s
\n",
		stream.ManifestUrl)
	fmt.Fprintf(writer, "Manifest Directory: %s
\n",
		stream.ManifestDirectory)
	buildLog := new(bytes.Buffer)
	manifestDirectory, err := stream.getManifest(b, streamName, "", buildLog)
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	defer os.RemoveAll(manifestDirectory)
	manifestFilename := path.Join(manifestDirectory, "manifest")
	manifestBytes, err := ioutil.ReadFile(manifestFilename)
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	var manifest manifestType
	if err := json.Unmarshal(manifestBytes, &manifest); err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	sourceStream := b.getNormalStream(manifest.SourceImage)
	if sourceStream == nil {
		fmt.Fprintf(writer, "SourceImage: %s
\n",
			manifest.SourceImage)
	} else {
		fmt.Fprintf(writer,
			"SourceImage: %s
\n",
			manifest.SourceImage, manifest.SourceImage)
	}
	fmt.Fprintln(writer, "Contents of manifest file:
")
	fmt.Fprintf(writer, "
\n", codeStyle)
	writer.Write(manifestBytes)
	fmt.Fprintln(writer, "

")
	packagesFile, err := os.Open(path.Join(manifestDirectory, "package-list"))
	if err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	}
	defer packagesFile.Close()
	fmt.Fprintln(writer, "Contents of package-list file:
")
	fmt.Fprintf(writer, "
\n", codeStyle)
	io.Copy(writer, packagesFile)
	fmt.Fprintln(writer, "

")
	if size, err := getTreeSize(manifestDirectory); err != nil {
		fmt.Fprintf(writer, "%s
\n", err)
		return
	} else {
		fmt.Fprintf(writer, "Manifest tree size: %s
\n",
			format.FormatBytes(size))
	}
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "Logging output:")
	fmt.Fprintln(writer, "
")
	io.Copy(writer, buildLog)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "")
}

func (b *Builder) showImageStreams(writer io.Writer) {
	streamNames := b.listNormalStreamNames()
	sort.Strings(streamNames)
	fmt.Fprintln(writer, `<table border="1">`)
	fmt.Fprintln(writer, "
")
	fmt.Fprintln(writer, "    Image Stream	")
	fmt.Fprintln(writer, "    ManifestUrl	")
	fmt.Fprintln(writer, "    ManifestDirectory	")
	fmt.Fprintln(writer, "
")
	for _, streamName := range streamNames {
		imageStream := b.getNormalStream(streamName)
		if imageStream == nil {
			continue
		}
		fmt.Fprintf(writer, "
\n")
		fmt.Fprintf(writer,
			"    %s	\n",
			streamName, streamName)
		fmt.Fprintf(writer, "    %s	\n", imageStream.ManifestUrl)
		fmt.Fprintf(writer, "    %s	\n", imageStream.ManifestDirectory)
		fmt.Fprintf(writer, "
\n")
	}
	fmt.Fprintln(writer, "

")
}
<|endoftext|>


<commit_before>package lib

import (
	"fmt"

	. "github.com/3d0c/gmf"
	"github.com/flavioribeiro/snickers/db"
	"github.com/flavioribeiro/snickers/types"
)

func FFMPEGEncode(jobID string) error {
	dbInstance, _ := db.GetDatabase()
	job, _ := dbInstance.RetrieveJob(jobID)
	return encode(job)
}

func addStream(codecName string, oc *FmtCtx, ist *Stream) (int, int, error) {
	var cc *CodecCtx
	var ost *Stream

	codec, err := FindEncoder(codecName)
	if err != nil {
		return 0, 0, err
	}

	if ost = oc.NewStream(codec); ost == nil {
		fmt.Println("unable to create stream in output context")
	}
	defer Release(ost)

	if cc = NewCodecCtx(codec); cc == nil {
		fmt.Println("unable to create codec context")
	}

	defer Release(cc)

	if oc.IsGlobalHeader() {
		cc.SetFlag(CODEC_FLAG_GLOBAL_HEADER)
	}

	if codec.IsExperimental() {
		cc.SetStrictCompliance(FF_COMPLIANCE_EXPERIMENTAL)
	}

	if cc.Type() == AVMEDIA_TYPE_AUDIO {
		cc.SetSampleFmt(ist.CodecCtx().SampleFmt())
		cc.SetSampleRate(ist.CodecCtx().SampleRate())
		cc.SetChannels(ist.CodecCtx().Channels())
		cc.SelectChannelLayout()
		cc.SelectSampleRate()

	}

	if cc.Type() == AVMEDIA_TYPE_VIDEO {
		cc.SetTimeBase(AVR{1, 25})
		cc.SetProfile(FF_PROFILE_MPEG4_SIMPLE)
		cc.SetDimension(ist.CodecCtx().Width(), ist.CodecCtx().Height())
		cc.SetPixFmt(ist.CodecCtx().PixFmt())
	}

	if err := cc.Open(nil); err != nil {
		fmt.Println(err.Error())
	}

	ost.SetCodecCtx(cc)

	return ist.Index(), ost.Index(), nil
}

// Encode function is responsible for encoding the file
func encode(job types.Job) error {
	dbInstance, _ := db.GetDatabase()
	srcFileName := job.LocalSource
	dstFileName := job.LocalDestination
	stMap := make(map[int]int, 0)
	var lastDelta int64

	inputCtx, err := NewInputCtx(srcFileName)
	if err != nil {
		job.Status = types.JobError
		job.Details = err.Error()
		dbInstance.UpdateJob(job.ID, job)
		return err
	}
	defer inputCtx.CloseInputAndRelease()

	outputCtx, err := NewOutputCtx(dstFileName)
	if err != nil {
		job.Status = types.JobError
		job.Details = err.Error()
		dbInstance.UpdateJob(job.ID, job)
		return err
	}
	defer outputCtx.CloseOutputAndRelease()

	job.Status = types.JobEncoding
	job.Details = "0%"
	dbInstance.UpdateJob(job.ID, job)

	srcVideoStream, _ := inputCtx.GetBestStream(AVMEDIA_TYPE_VIDEO)
	i, o, _ := addStream("mpeg4", outputCtx, srcVideoStream)
	stMap[i] = o

	srcAudioStream, _ := inputCtx.GetBestStream(AVMEDIA_TYPE_AUDIO)
	i, o, _ = addStream("aac", outputCtx, srcAudioStream)
	stMap[i] = o

	if err := outputCtx.WriteHeader(); err != nil {
		return err
	}

	for packet := range inputCtx.GetNewPackets() {
		ist, err := inputCtx.GetStream(packet.StreamIndex())
		if err != nil {
			return err
		}
		ost, err := outputCtx.GetStream(stMap[ist.Index()])
		if err != nil {
			return err
		}

		for frame := range packet.Frames(ist.CodecCtx()) {
			if ost.IsAudio() {
				fsTb := AVR{1, ist.CodecCtx().SampleRate()}
				outTb := AVR{1, ist.CodecCtx().SampleRate()}

				frame.SetPts(packet.Pts())

				pts := RescaleDelta(ist.TimeBase(), frame.Pts(), fsTb.AVRational(), frame.NbSamples(), &lastDelta, outTb.AVRational())

				frame.
					SetNbSamples(ost.CodecCtx().FrameSize()).
					SetFormat(ost.CodecCtx().SampleFmt()).
					SetChannelLayout(ost.CodecCtx().ChannelLayout()).
					SetPts(pts)
			} else {
				frame.SetPts(ost.Pts)
			}

			if p, ready, _ := frame.EncodeNewPacket(ost.CodecCtx()); ready {
				if p.Pts() != AV_NOPTS_VALUE {
					p.SetPts(RescaleQ(p.Pts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				if p.Dts() != AV_NOPTS_VALUE {
					p.SetDts(RescaleQ(p.Dts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				p.SetStreamIndex(ost.Index())

				if err := outputCtx.WritePacket(p); err != nil {
					return err
				}
				Release(p)
			}

			ost.Pts++
		}
		Release(packet)
	}

	// Flush encoders
	// @todo refactor it (should be a better way)
	for i := 0; i < outputCtx.StreamsCnt(); i++ {
		ist, err := inputCtx.GetStream(0)
		if err != nil {
			return err
		}
		ost, err := outputCtx.GetStream(stMap[ist.Index()])
		if err != nil {
			return err
		}

		frame := NewFrame()

		for {
			if p, ready, _ := frame.FlushNewPacket(ost.CodecCtx()); ready {
				if p.Pts() != AV_NOPTS_VALUE {
					p.SetPts(RescaleQ(p.Pts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				if p.Dts() != AV_NOPTS_VALUE {
					p.SetDts(RescaleQ(p.Dts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				p.SetStreamIndex(ost.Index())

				if err := outputCtx.WritePacket(p); err != nil {
					return err
				}
				Release(p)
			} else {
				Release(p)
				break
			}

			ost.Pts++
		}

		Release(frame)
	}

	return nil
}
<commit_msg>ffmpeg_encoder: remove useless abstraction<commit_after>package lib

import (
	"fmt"

	. "github.com/3d0c/gmf"
	"github.com/flavioribeiro/snickers/db"
	"github.com/flavioribeiro/snickers/types"
)

func addStream(codecName string, oc *FmtCtx, ist *Stream) (int, int, error) {
	var cc *CodecCtx
	var ost *Stream

	codec, err := FindEncoder(codecName)
	if err != nil {
		return 0, 0, err
	}

	if ost = oc.NewStream(codec); ost == nil {
		fmt.Println("unable to create stream in output context")
	}
	defer Release(ost)

	if cc = NewCodecCtx(codec); cc == nil {
		fmt.Println("unable to create codec context")
	}

	defer Release(cc)

	if oc.IsGlobalHeader() {
		cc.SetFlag(CODEC_FLAG_GLOBAL_HEADER)
	}

	if codec.IsExperimental() {
		cc.SetStrictCompliance(FF_COMPLIANCE_EXPERIMENTAL)
	}

	if cc.Type() == AVMEDIA_TYPE_AUDIO {
		cc.SetSampleFmt(ist.CodecCtx().SampleFmt())
		cc.SetSampleRate(ist.CodecCtx().SampleRate())
		cc.SetChannels(ist.CodecCtx().Channels())
		cc.SelectChannelLayout()
		cc.SelectSampleRate()

	}

	if cc.Type() == AVMEDIA_TYPE_VIDEO {
		cc.SetTimeBase(AVR{1, 25})
		cc.SetProfile(FF_PROFILE_MPEG4_SIMPLE)
		cc.SetDimension(ist.CodecCtx().Width(), ist.CodecCtx().Height())
		cc.SetPixFmt(ist.CodecCtx().PixFmt())
	}

	if err := cc.Open(nil); err != nil {
		fmt.Println(err.Error())
	}

	ost.SetCodecCtx(cc)

	return ist.Index(), ost.Index(), nil
}

// FFMPEGEncode function is responsible for encoding the file
func FFMPEGEncode(jobID string) error {
	dbInstance, _ := db.GetDatabase()
	job, _ := dbInstance.RetrieveJob(jobID)
	srcFileName := job.LocalSource
	dstFileName := job.LocalDestination
	stMap := make(map[int]int, 0)
	var lastDelta int64

	inputCtx, err := NewInputCtx(srcFileName)
	if err != nil {
		job.Status = types.JobError
		job.Details = err.Error()
		dbInstance.UpdateJob(job.ID, job)
		return err
	}
	defer inputCtx.CloseInputAndRelease()

	outputCtx, err := NewOutputCtx(dstFileName)
	if err != nil {
		job.Status = types.JobError
		job.Details = err.Error()
		dbInstance.UpdateJob(job.ID, job)
		return err
	}
	defer outputCtx.CloseOutputAndRelease()

	job.Status = types.JobEncoding
	job.Details = "0%"
	dbInstance.UpdateJob(job.ID, job)

	srcVideoStream, _ := inputCtx.GetBestStream(AVMEDIA_TYPE_VIDEO)
	i, o, _ := addStream("mpeg4", outputCtx, srcVideoStream)
	stMap[i] = o

	srcAudioStream, _ := inputCtx.GetBestStream(AVMEDIA_TYPE_AUDIO)
	i, o, _ = addStream("aac", outputCtx, srcAudioStream)
	stMap[i] = o

	if err := outputCtx.WriteHeader(); err != nil {
		return err
	}

	for packet := range inputCtx.GetNewPackets() {
		ist, err := inputCtx.GetStream(packet.StreamIndex())
		if err != nil {
			return err
		}
		ost, err := outputCtx.GetStream(stMap[ist.Index()])
		if err != nil {
			return err
		}

		for frame := range packet.Frames(ist.CodecCtx()) {
			if ost.IsAudio() {
				fsTb := AVR{1, ist.CodecCtx().SampleRate()}
				outTb := AVR{1, ist.CodecCtx().SampleRate()}

				frame.SetPts(packet.Pts())

				pts := RescaleDelta(ist.TimeBase(), frame.Pts(), fsTb.AVRational(), frame.NbSamples(), &lastDelta, outTb.AVRational())

				frame.
					SetNbSamples(ost.CodecCtx().FrameSize()).
					SetFormat(ost.CodecCtx().SampleFmt()).
					SetChannelLayout(ost.CodecCtx().ChannelLayout()).
					SetPts(pts)
			} else {
				frame.SetPts(ost.Pts)
			}

			if p, ready, _ := frame.EncodeNewPacket(ost.CodecCtx()); ready {
				if p.Pts() != AV_NOPTS_VALUE {
					p.SetPts(RescaleQ(p.Pts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				if p.Dts() != AV_NOPTS_VALUE {
					p.SetDts(RescaleQ(p.Dts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				p.SetStreamIndex(ost.Index())

				if err := outputCtx.WritePacket(p); err != nil {
					return err
				}
				Release(p)
			}

			ost.Pts++
		}
		Release(packet)
	}

	// Flush encoders
	// @todo refactor it (should be a better way)
	for i := 0; i < outputCtx.StreamsCnt(); i++ {
		ist, err := inputCtx.GetStream(0)
		if err != nil {
			return err
		}
		ost, err := outputCtx.GetStream(stMap[ist.Index()])
		if err != nil {
			return err
		}

		frame := NewFrame()

		for {
			if p, ready, _ := frame.FlushNewPacket(ost.CodecCtx()); ready {
				if p.Pts() != AV_NOPTS_VALUE {
					p.SetPts(RescaleQ(p.Pts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				if p.Dts() != AV_NOPTS_VALUE {
					p.SetDts(RescaleQ(p.Dts(), ost.CodecCtx().TimeBase(), ost.TimeBase()))
				}

				p.SetStreamIndex(ost.Index())

				if err := outputCtx.WritePacket(p); err != nil {
					return err
				}
				Release(p)
			} else {
				Release(p)
				break
			}

			ost.Pts++
		}

		Release(frame)
	}

	return nil
}
<|endoftext|>


<commit_before>package state

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/omniscale/imposm3/logging"
	"github.com/omniscale/imposm3/parser/pbf"
	"io"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

var log = logging.NewLogger("diff")

type DiffState struct {
	Time     time.Time
	Sequence int32
	Url      string
}

func (d DiffState) String() string {
	return fmt.Sprintf("Diff #%d from %s", d.Sequence, d.Time.Local())
}

func (d DiffState) WriteToFile(file string) error {
	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer f.Close()

	writer := bufio.NewWriter(f)

	lines := []string{}
	lines = append(lines, "timestamp="+d.Time.Format("2006-01-02T15\\:04\\:05Z"))
	if d.Sequence != 0 {
		lines = append(lines, "sequenceNumber="+fmt.Sprintf("%d", d.Sequence))
	}
	lines = append(lines, "replicationUrl="+d.Url)

	for _, line := range lines {
		_, err = writer.WriteString(line + "\n")
		if err != nil {
			return err
		}
	}
	return writer.Flush()
}

func WriteLastState(cacheDir string, state *DiffState) error {
	stateFile := path.Join(cacheDir, "last.state.txt")
	return state.WriteToFile(stateFile)
}

func ParseFromOsc(oscFile string) (*DiffState, error) {
	var stateFile string
	if !strings.HasSuffix(oscFile, ".osc.gz") {
		log.Warn("cannot read state file for non .osc.gz files")
		return nil, nil
	}

	stateFile = oscFile[:len(oscFile)-len(".osc.gz")] + ".state.txt"
	if _, err := os.Stat(stateFile); os.IsNotExist(err) {
		log.Warn("cannot find state file ", stateFile)
		return nil, nil
	}

	f, err := os.Open(stateFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return ParseFile(stateFile)
}

func FromPbf(pbfFile *pbf.Pbf) *DiffState {
	var timestamp time.Time
	if pbfFile.Header.Time.Unix() != 0 {
		timestamp = pbfFile.Header.Time
	} else {
		fstat, err := os.Stat(pbfFile.Filename)
		if err != nil {
			log.Warn("unable to stat pbffile: ", err)
			return nil
		}
		timestamp = fstat.ModTime()
	}

	replicationUrl := "http://planet.openstreetmap.org/replication/minute/"

	seq := estimateSequence(replicationUrl, timestamp)
	if seq != 0 {
		// start a two hours earlier
		seq -= 120
	}
	return &DiffState{Time: timestamp, Url: replicationUrl, Sequence: seq}
}

func ParseFile(stateFile string) (*DiffState, error) {
	f, err := os.Open(stateFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return Parse(f)
}

func Parse(f io.Reader) (*DiffState, error) {
	values, err := parseSimpleIni(f)
	if err != nil {
		return nil, err
	}

	timestamp, err := parseTimeStamp(values["timestamp"])
	if err != nil {
		return nil, err
	}
	sequence, err := parseSequence(values["sequenceNumber"])
	if err != nil {
		return nil, err
	}

	url := values["replicationUrl"]
	return &DiffState{timestamp, sequence, url}, nil
}

func ParseLastState(cacheDir string) (*DiffState, error) {
	stateFile := path.Join(cacheDir, "last.state.txt")
	if _, err := os.Stat(stateFile); os.IsNotExist(err) {
		return nil, err
	}
	return ParseFile(stateFile)
}

func parseSimpleIni(f io.Reader) (map[string]string, error) {
	result := make(map[string]string)

	reader := bufio.NewScanner(f)
	for reader.Scan() {
		line := reader.Text()
		if line != "" && line[0] == '#' {
			continue
		}
		if strings.Contains(line, "=") {
			keyVal := strings.SplitN(line, "=", 2)
			result[strings.TrimSpace(keyVal[0])] = strings.TrimSpace(keyVal[1])
		}

	}
	if err := reader.Err(); err != nil {
		return nil, err
	}

	return result, nil
}

func parseTimeStamp(value string) (time.Time, error) {
	if value == "" {
		return time.Time{}, errors.New("missing timestamp in state")
	}
	return time.Parse("2006-01-02T15\\:04\\:05Z", value)
}

func parseSequence(value string) (int32, error) {
	if value == "" {
		log.Warn("missing sequenceNumber in state file")
		return 0, nil
	}
	val, err := strconv.ParseInt(value, 10, 32)
	return int32(val), err
}

func currentState(url string) (*DiffState, error) {
	resp, err := http.Get(url + "state.txt")
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("invalid repsonse: %v", resp))
	}
	defer resp.Body.Close()
	return Parse(resp.Body)
}

func estimateSequence(url string, timestamp time.Time) int32 {
	state, err := currentState(url)
	if err != nil {
		log.Warn("unabnle to fetch current state from ", url, ":", err)
		return 0
	}
	behind := state.Time.Sub(timestamp)
	return state.Sequence - int32(behind.Minutes())
}
<commit_msg>do not write last.state.txt if it failed to estimate sequence number<commit_after>package state

import (
	"bufio"
	"errors"
	"fmt"
	"io"
	"net/http"
	"os"
	"path"
	"strconv"
	"strings"
	"time"

	"github.com/omniscale/imposm3/logging"
	"github.com/omniscale/imposm3/parser/pbf"
)

var log = logging.NewLogger("diff")

type DiffState struct {
	Time     time.Time
	Sequence int32
	Url      string
}

func (d DiffState) String() string {
	return fmt.Sprintf("Diff #%d from %s", d.Sequence, d.Time.Local())
}

func (d DiffState) WriteToFile(file string) error {
	f, err := os.Create(file)
	if err != nil {
		return err
	}
	defer f.Close()

	writer := bufio.NewWriter(f)

	lines := []string{}
	lines = append(lines, "timestamp="+d.Time.Format(timestampFormat))
	if d.Sequence != 0 {
		lines = append(lines, "sequenceNumber="+fmt.Sprintf("%d", d.Sequence))
	}
	lines = append(lines, "replicationUrl="+d.Url)

	for _, line := range lines {
		_, err = writer.WriteString(line + "\n")
		if err != nil {
			return err
		}
	}
	return writer.Flush()
}

func WriteLastState(cacheDir string, state *DiffState) error {
	stateFile := path.Join(cacheDir, "last.state.txt")
	return state.WriteToFile(stateFile)
}

func ParseFromOsc(oscFile string) (*DiffState, error) {
	var stateFile string
	if !strings.HasSuffix(oscFile, ".osc.gz") {
		log.Warn("cannot read state file for non .osc.gz files")
		return nil, nil
	}

	stateFile = oscFile[:len(oscFile)-len(".osc.gz")] + ".state.txt"
	if _, err := os.Stat(stateFile); os.IsNotExist(err) {
		log.Warn("cannot find state file ", stateFile)
		return nil, nil
	}

	f, err := os.Open(stateFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return ParseFile(stateFile)
}

func FromPbf(pbfFile *pbf.Pbf) *DiffState {
	var timestamp time.Time
	if pbfFile.Header.Time.Unix() != 0 {
		timestamp = pbfFile.Header.Time
	} else {
		fstat, err := os.Stat(pbfFile.Filename)
		if err != nil {
			log.Warn("unable to stat pbffile: ", err)
			return nil
		}
		timestamp = fstat.ModTime()
	}

	replicationUrl := "http://planet.openstreetmap.org/replication/minute/"

	seq := estimateSequence(replicationUrl, timestamp)
	if seq == 0 {
		return nil
	}

	// start two hours earlier
	seq -= 120
	return &DiffState{Time: timestamp, Url: replicationUrl, Sequence: seq}
}

func ParseFile(stateFile string) (*DiffState, error) {
	f, err := os.Open(stateFile)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	return Parse(f)
}

func Parse(f io.Reader) (*DiffState, error) {
	values, err := parseSimpleIni(f)
	if err != nil {
		return nil, err
	}

	timestamp, err := parseTimeStamp(values["timestamp"])
	if err != nil {
		return nil, err
	}
	sequence, err := parseSequence(values["sequenceNumber"])
	if err != nil {
		return nil, err
	}

	url := values["replicationUrl"]
	return &DiffState{timestamp, sequence, url}, nil
}

func ParseLastState(cacheDir string) (*DiffState, error) {
	stateFile := path.Join(cacheDir, "last.state.txt")
	if _, err := os.Stat(stateFile); os.IsNotExist(err) {
		return nil, err
	}
	return ParseFile(stateFile)
}

func parseSimpleIni(f io.Reader) (map[string]string, error) {
	result := make(map[string]string)

	reader := bufio.NewScanner(f)
	for reader.Scan() {
		line := reader.Text()
		if line != "" && line[0] == '#' {
			continue
		}
		if strings.Contains(line, "=") {
			keyVal := strings.SplitN(line, "=", 2)
			result[strings.TrimSpace(keyVal[0])] = strings.TrimSpace(keyVal[1])
		}

	}
	if err := reader.Err(); err != nil {
		return nil, err
	}

	return result, nil
}

const timestampFormat = "2006-01-02T15\\:04\\:05Z"

func parseTimeStamp(value string) (time.Time, error) {
	if value == "" {
		return time.Time{}, errors.New("missing timestamp in state")
	}
	return time.Parse(timestampFormat, value)
}

func parseSequence(value string) (int32, error) {
	if value == "" {
		log.Warn("missing sequenceNumber in state file")
		return 0, nil
	}
	val, err := strconv.ParseInt(value, 10, 32)
	return int32(val), err
}

func currentState(url string) (*DiffState, error) {
	resp, err := http.Get(url + "state.txt")
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != 200 {
		return nil, errors.New(fmt.Sprintf("invalid repsonse: %v", resp))
	}
	defer resp.Body.Close()
	return Parse(resp.Body)
}

func estimateSequence(url string, timestamp time.Time) int32 {
	state, err := currentState(url)
	if err != nil {
		// try a second time befor failing
		log.Warn("unable to fetch current state from ", url, ":", err, ", retry in 30s")
		time.Sleep(time.Second * 30)
		state, err = currentState(url)
		if err != nil {
			log.Warn("unable to fetch current state from ", url, ":", err, ", giving up")
			return 0
		}
	}

	behind := state.Time.Sub(timestamp)
	return state.Sequence - int32(behind.Minutes())
}
<|endoftext|>


<commit_before>package gumble // import "layeh.com/gumble/gumble"

// Permission is a bitmask of permissions given to a certain user.
type Permission int

// Permissions that can be applied in any channel.
const (
	PermissionWrite Permission = 1 << iota
	PermissionTraverse
	PermissionEnter
	PermissionSpeak
	PermissionMuteDeafen
	PermissionMove
	PermissionMakeChannel
	PermissionLinkChannel
	PermissionWhisper
	PermissionTextMessage
	PermissionMakeTemporaryChannel
)

// Permissions that can only be applied in the root channel.
const (
	PermissionKick Permission = 0x10000 << iota
	PermissionBan
	PermissionRegister
	PermissionRegisterSelf
)
<commit_msg>add Permission.Has<commit_after>package gumble // import "layeh.com/gumble/gumble"

// Permission is a bitmask of permissions given to a certain user.
type Permission int

// Permissions that can be applied in any channel.
const (
	PermissionWrite Permission = 1 << iota
	PermissionTraverse
	PermissionEnter
	PermissionSpeak
	PermissionMuteDeafen
	PermissionMove
	PermissionMakeChannel
	PermissionLinkChannel
	PermissionWhisper
	PermissionTextMessage
	PermissionMakeTemporaryChannel
)

// Permissions that can only be applied in the root channel.
const (
	PermissionKick Permission = 0x10000 << iota
	PermissionBan
	PermissionRegister
	PermissionRegisterSelf
)

// Has returns true if the Permission p contains Permission o has part of its
// bitmask.
func (p Permission) Has(o Permission) bool {
	return p&o != 0
}
<|endoftext|>


<commit_before>package gvutils

import (
	"testing"
)

func TestVersionFlag(t *testing.T) {
	expectedStr := "Current Version is 0.0, built at 2016-08-20T12:30:00-0400"
	Version = "0.0"
	BuildTime = "2016-08-20T12:30:00-0400"
	result := DisplayVersion()
	if result != expectedStr {
		t.Fatalf("Expected result to be:\n%s, but got instead:\n%s\n", expectedStr, result)
	}
}
<commit_msg>Added test for current flags<commit_after>package gvutils

import ()

func ExampleVersionFlag() {
	Version = "0.0"
	BuildTime = "2016-08-20T12:30:00-0400"
	DisplayVersion()
	// Output: Current Version is 0.0, built at 2016-08-20T12:30:00-0400.
}
<|endoftext|>


<commit_before>//  Copyright (c) 2014 Couchbase, Inc.
//  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 boltdb

import (
	"fmt"

	"github.com/blevesearch/bleve/index/store"
)

type Writer struct {
	store *Store
}

func (w *Writer) NewBatch() store.KVBatch {
	return store.NewEmulatedBatch(w.store.mo)
}

func (w *Writer) NewBatchEx(options store.KVBatchOptions) ([]byte, store.KVBatch, error) {
	return make([]byte, options.TotalBytes), w.NewBatch(), nil
}

func (w *Writer) ExecuteBatch(batch store.KVBatch) (err error) {

	emulatedBatch, ok := batch.(*store.EmulatedBatch)
	if !ok {
		return fmt.Errorf("wrong type of batch")
	}

	tx, err := w.store.db.Begin(true)
	if err != nil {
		return
	}
	// defer function to ensure that once started,
	// we either Commit tx or Rollback
	defer func() {
		// if nothing went wrong, commit
		if err == nil {
			// careful to catch error here too
			err = tx.Commit()
		} else {
			// caller should see error that caused abort,
			// not success or failure of Rollback itself
			tx.Rollback()
		}
	}()
	defer tx.Rollback()

	bucket := tx.Bucket([]byte(w.store.bucket))
	bucket.FillPercent = w.store.fillPercent

	for k, mergeOps := range emulatedBatch.Merger.Merges {
		kb := []byte(k)
		existingVal := bucket.Get(kb)
		mergedVal, fullMergeOk := w.store.mo.FullMerge(kb, existingVal, mergeOps)
		if !fullMergeOk {
			err = fmt.Errorf("merge operator returned failure")
			return
		}
		err = bucket.Put(kb, mergedVal)
		if err != nil {
			return
		}
	}

	for _, op := range emulatedBatch.Ops {
		if op.V != nil {
			err = bucket.Put(op.K, op.V)
			if err != nil {
				return
			}
		} else {
			err = bucket.Delete(op.K)
			if err != nil {
				return
			}
		}
	}
	return
}

func (w *Writer) Close() error {
	return nil
}
<commit_msg>Now, without the rollback<commit_after>//  Copyright (c) 2014 Couchbase, Inc.
//  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 boltdb

import (
	"fmt"

	"github.com/blevesearch/bleve/index/store"
)

type Writer struct {
	store *Store
}

func (w *Writer) NewBatch() store.KVBatch {
	return store.NewEmulatedBatch(w.store.mo)
}

func (w *Writer) NewBatchEx(options store.KVBatchOptions) ([]byte, store.KVBatch, error) {
	return make([]byte, options.TotalBytes), w.NewBatch(), nil
}

func (w *Writer) ExecuteBatch(batch store.KVBatch) (err error) {

	emulatedBatch, ok := batch.(*store.EmulatedBatch)
	if !ok {
		return fmt.Errorf("wrong type of batch")
	}

	tx, err := w.store.db.Begin(true)
	if err != nil {
		return
	}
	// defer function to ensure that once started,
	// we either Commit tx or Rollback
	defer func() {
		// if nothing went wrong, commit
		if err == nil {
			// careful to catch error here too
			err = tx.Commit()
		} else {
			// caller should see error that caused abort,
			// not success or failure of Rollback itself
			tx.Rollback()
		}
	}()

	bucket := tx.Bucket([]byte(w.store.bucket))
	bucket.FillPercent = w.store.fillPercent

	for k, mergeOps := range emulatedBatch.Merger.Merges {
		kb := []byte(k)
		existingVal := bucket.Get(kb)
		mergedVal, fullMergeOk := w.store.mo.FullMerge(kb, existingVal, mergeOps)
		if !fullMergeOk {
			err = fmt.Errorf("merge operator returned failure")
			return
		}
		err = bucket.Put(kb, mergedVal)
		if err != nil {
			return
		}
	}

	for _, op := range emulatedBatch.Ops {
		if op.V != nil {
			err = bucket.Put(op.K, op.V)
			if err != nil {
				return
			}
		} else {
			err = bucket.Delete(op.K)
			if err != nil {
				return
			}
		}
	}
	return
}

func (w *Writer) Close() error {
	return nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"fmt"
	"os"
	"strconv"

	middleware "github.com/go-openapi/runtime/middleware"

	_ "github.com/openshift/origin/pkg/api/install"
	serverapi "github.com/openshift/origin/pkg/cmd/server/api"
	ocon "github.com/redhatanalytics/oshinko-rest/helpers/containers"
	odc "github.com/redhatanalytics/oshinko-rest/helpers/deploymentconfigs"
	opt "github.com/redhatanalytics/oshinko-rest/helpers/podtemplates"
	osv "github.com/redhatanalytics/oshinko-rest/helpers/services"
	"github.com/redhatanalytics/oshinko-rest/restapi/operations/clusters"

	"github.com/redhatanalytics/oshinko-rest/models"
	"strconv"
)

func sparkMasterURL(name string, port *osv.OServicePort) string {
	return "spark://" + name + ":" + strconv.Itoa(port.ServicePort.Port)
}

func sparkWorker(namespace string,
	image string,
	replicas int, masterurl string) *odc.ODeploymentConfig {

	// Create the basic deployment config
	dc := odc.DeploymentConfig(
		"spark-worker",
		namespace).TriggerOnConfigChange().RollingStrategy().Replicas(replicas)

	// We will use a "name" label with the name of the deployment config
	// as a selector for the pods controlled by this deployment.
	// Set the selector on the deployment config ...
	dc = dc.PodSelector("name", dc.Name)

	// ... and create a pod template spec with the matching label
	pt := opt.PodTemplateSpec().SetLabels(dc.GetPodSelectors())

	// Create a container with the correct start command
	cont := ocon.Container(
		dc.Name,
		image).Command("/start-worker", masterurl)

	// Finally, assign the container to the pod template spec and
	// assign the pod template spec to the deployment config
	return dc.PodTemplateSpec(pt.Containers(cont))
}

func sparkMaster(namespace string, image string) *odc.ODeploymentConfig {

	// Create the basic deployment config
	// dc.Name will be spark-master-<suffix>
	dc := odc.DeploymentConfig(
		"spark-master",
		namespace).TriggerOnConfigChange().RollingStrategy()

	// We will use a "name" label with the name of the deployment config
	// as a selector for the pods controlled by this deployment.
	// Set the selector on the deployment config ...
	dc = dc.PodSelector("name", dc.Name)

	// ... and create a pod template spec with the matching label
	pt := opt.PodTemplateSpec().SetLabels(dc.GetPodSelectors())

	// Create a container with the correct ports and start command
	masterp := ocon.ContainerPort("spark-master", 7077)
	webp := ocon.ContainerPort("spark-webui", 8080)
	cont := ocon.Container(
		dc.Name,
		image).Command("/start-master",
		dc.Name).Ports(masterp, webp)

	// Finally, assign the container to the pod template spec and
	// assign the pod template spec to the deployment config
	return dc.PodTemplateSpec(pt.Containers(cont))
}

func Service(name string, port int, mylabels, podlabels map[string]string) (*osv.OService, *osv.OServicePort) {
	p := osv.ServicePort(port).TargetPort(port)
	return osv.Service(name).SetLabels(mylabels).PodSelectors(podlabels).Ports(p), p
}

// CreateClusterResponse create a cluster and return the representation
func CreateClusterResponse(params clusters.CreateClusterParams) middleware.Responder {
	// create a cluster here
	// INFO(elmiko) my thinking on creating clusters is that we should use a
	// label on the items we create with kubernetes so that we can get them
	// all with a request.
	// in addition to labels for general identification, we should then use
	// annotations on objects to help further refine what we are dealing with.

	namespace := os.Getenv("OSHIKO_CLUSTER_NAMESPACE")
	configfile := os.Getenv("OSHINKO_KUBE_CONFIG")
	image := os.Getenv("OSHINKO_CLUSTER_IMAGE")
	if namespace == "" || configfile == "" || image == "" {
		payload := makeSingleErrorResponse(501, "Missing Env",
			"OSHIKO_CLUSTER_NAMESPACE, OSHINKO_KUBE_CONFIG, and OSHINKO_CLUSTER_IMAGE env vars must be set")
		return clusters.NewCreateClusterDefault(501).WithPayload(payload)
	}

	// kube rest client
	client, _, err := serverapi.GetKubeClient(configfile)
	if err != nil {
		// handle error
	}

	// openshift rest client
	osclient, _, err := serverapi.GetOpenShiftClient(configfile)
	if err != nil {
		//handle error
	}

	// deployment config client
	dcc := osclient.DeploymentConfigs(namespace)

	// Make master deployment config
	// Ignoring master-count for now, leave it defaulted at 1
	masterdc := sparkMaster(namespace, image)

	// Make master services
	mastersv, masterp := Service(masterdc.Name,
		masterdc.FindPort("spark-master"),
		masterdc.GetPodSelectors(), masterdc.GetPodSelectors())

	websv, _ := Service(masterdc.Name+"webui",
		masterdc.FindPort("spark-webui"),
		masterdc.GetPodSelectors(),
		masterdc.GetPodSelectors())

	// Make worker deployment config
	masterurl := sparkMasterURL(mastersv.Name, masterp)
	workerdc := sparkWorker(
		namespace,
		image,
		int(*params.Cluster.WorkerCount), masterurl)

	// Launch all of the objects
	_, err = dcc.Create(&masterdc.DeploymentConfig)
	if err != nil {
		fmt.Println(err)
	}
	dcc.Create(&workerdc.DeploymentConfig)
	client.Services(namespace).Create(&mastersv.Service)
	client.Services(namespace).Create(&websv.Service)

	cluster := &models.SingleCluster{&models.ClusterModel{}}
	cluster.Cluster.Name = params.Cluster.Name
	cluster.Cluster.WorkerCount = params.Cluster.WorkerCount
	cluster.Cluster.MasterCount = params.Cluster.MasterCount
	return clusters.NewCreateClusterCreated().WithLocation(masterurl).WithPayload(cluster)
}

// DeleteClusterResponse delete a cluster
func DeleteClusterResponse(params clusters.DeleteSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.DeleteSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// FindClustersResponse find a cluster and return its representation
func FindClustersResponse() middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.FindClusters has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// FindSingleClusterResponse find a cluster and return its representation
func FindSingleClusterResponse(clusters.FindSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.FindSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// UpdateSingleClusterResponse update a cluster and return the new representation
func UpdateSingleClusterResponse(params clusters.UpdateSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.UpdateSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}
<commit_msg>Fix typo in env var<commit_after>package handlers

import (
	"fmt"
	"os"
	"strconv"

	middleware "github.com/go-openapi/runtime/middleware"

	_ "github.com/openshift/origin/pkg/api/install"
	serverapi "github.com/openshift/origin/pkg/cmd/server/api"
	ocon "github.com/redhatanalytics/oshinko-rest/helpers/containers"
	odc "github.com/redhatanalytics/oshinko-rest/helpers/deploymentconfigs"
	opt "github.com/redhatanalytics/oshinko-rest/helpers/podtemplates"
	osv "github.com/redhatanalytics/oshinko-rest/helpers/services"
	"github.com/redhatanalytics/oshinko-rest/restapi/operations/clusters"

	"github.com/redhatanalytics/oshinko-rest/models"
	"strconv"
)

func sparkMasterURL(name string, port *osv.OServicePort) string {
	return "spark://" + name + ":" + strconv.Itoa(port.ServicePort.Port)
}

func sparkWorker(namespace string,
	image string,
	replicas int, masterurl string) *odc.ODeploymentConfig {

	// Create the basic deployment config
	dc := odc.DeploymentConfig(
		"spark-worker",
		namespace).TriggerOnConfigChange().RollingStrategy().Replicas(replicas)

	// We will use a "name" label with the name of the deployment config
	// as a selector for the pods controlled by this deployment.
	// Set the selector on the deployment config ...
	dc = dc.PodSelector("name", dc.Name)

	// ... and create a pod template spec with the matching label
	pt := opt.PodTemplateSpec().SetLabels(dc.GetPodSelectors())

	// Create a container with the correct start command
	cont := ocon.Container(
		dc.Name,
		image).Command("/start-worker", masterurl)

	// Finally, assign the container to the pod template spec and
	// assign the pod template spec to the deployment config
	return dc.PodTemplateSpec(pt.Containers(cont))
}

func sparkMaster(namespace string, image string) *odc.ODeploymentConfig {

	// Create the basic deployment config
	// dc.Name will be spark-master-<suffix>
	dc := odc.DeploymentConfig(
		"spark-master",
		namespace).TriggerOnConfigChange().RollingStrategy()

	// We will use a "name" label with the name of the deployment config
	// as a selector for the pods controlled by this deployment.
	// Set the selector on the deployment config ...
	dc = dc.PodSelector("name", dc.Name)

	// ... and create a pod template spec with the matching label
	pt := opt.PodTemplateSpec().SetLabels(dc.GetPodSelectors())

	// Create a container with the correct ports and start command
	masterp := ocon.ContainerPort("spark-master", 7077)
	webp := ocon.ContainerPort("spark-webui", 8080)
	cont := ocon.Container(
		dc.Name,
		image).Command("/start-master",
		dc.Name).Ports(masterp, webp)

	// Finally, assign the container to the pod template spec and
	// assign the pod template spec to the deployment config
	return dc.PodTemplateSpec(pt.Containers(cont))
}

func Service(name string, port int, mylabels, podlabels map[string]string) (*osv.OService, *osv.OServicePort) {
	p := osv.ServicePort(port).TargetPort(port)
	return osv.Service(name).SetLabels(mylabels).PodSelectors(podlabels).Ports(p), p
}

// CreateClusterResponse create a cluster and return the representation
func CreateClusterResponse(params clusters.CreateClusterParams) middleware.Responder {
	// create a cluster here
	// INFO(elmiko) my thinking on creating clusters is that we should use a
	// label on the items we create with kubernetes so that we can get them
	// all with a request.
	// in addition to labels for general identification, we should then use
	// annotations on objects to help further refine what we are dealing with.

	namespace := os.Getenv("OSHINKO_CLUSTER_NAMESPACE")
	configfile := os.Getenv("OSHINKO_KUBE_CONFIG")
	image := os.Getenv("OSHINKO_CLUSTER_IMAGE")
	if namespace == "" || configfile == "" || image == "" {
		payload := makeSingleErrorResponse(501, "Missing Env",
			"OSHIKO_CLUSTER_NAMESPACE, OSHINKO_KUBE_CONFIG, and OSHINKO_CLUSTER_IMAGE env vars must be set")
		return clusters.NewCreateClusterDefault(501).WithPayload(payload)
	}

	// kube rest client
	client, _, err := serverapi.GetKubeClient(configfile)
	if err != nil {
		// handle error
	}

	// openshift rest client
	osclient, _, err := serverapi.GetOpenShiftClient(configfile)
	if err != nil {
		//handle error
	}

	// deployment config client
	dcc := osclient.DeploymentConfigs(namespace)

	// Make master deployment config
	// Ignoring master-count for now, leave it defaulted at 1
	masterdc := sparkMaster(namespace, image)

	// Make master services
	mastersv, masterp := Service(masterdc.Name,
		masterdc.FindPort("spark-master"),
		masterdc.GetPodSelectors(), masterdc.GetPodSelectors())

	websv, _ := Service(masterdc.Name+"webui",
		masterdc.FindPort("spark-webui"),
		masterdc.GetPodSelectors(),
		masterdc.GetPodSelectors())

	// Make worker deployment config
	masterurl := sparkMasterURL(mastersv.Name, masterp)
	workerdc := sparkWorker(
		namespace,
		image,
		int(*params.Cluster.WorkerCount), masterurl)

	// Launch all of the objects
	_, err = dcc.Create(&masterdc.DeploymentConfig)
	if err != nil {
		fmt.Println(err)
	}
	dcc.Create(&workerdc.DeploymentConfig)
	client.Services(namespace).Create(&mastersv.Service)
	client.Services(namespace).Create(&websv.Service)

	cluster := &models.SingleCluster{&models.ClusterModel{}}
	cluster.Cluster.Name = params.Cluster.Name
	cluster.Cluster.WorkerCount = params.Cluster.WorkerCount
	cluster.Cluster.MasterCount = params.Cluster.MasterCount
	return clusters.NewCreateClusterCreated().WithLocation(masterurl).WithPayload(cluster)
}

// DeleteClusterResponse delete a cluster
func DeleteClusterResponse(params clusters.DeleteSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.DeleteSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// FindClustersResponse find a cluster and return its representation
func FindClustersResponse() middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.FindClusters has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// FindSingleClusterResponse find a cluster and return its representation
func FindSingleClusterResponse(clusters.FindSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.FindSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}

// UpdateSingleClusterResponse update a cluster and return the new representation
func UpdateSingleClusterResponse(params clusters.UpdateSingleClusterParams) middleware.Responder {
	payload := makeSingleErrorResponse(501, "Not Implemented",
		"operation clusters.UpdateSingleCluster has not yet been implemented")
	return clusters.NewCreateClusterDefault(501).WithPayload(payload)
}
<|endoftext|>


<commit_before>// Generated by: main
// TypeWriter: repository
// Directive: +gen on Session

package ressources

import (
	"database/sql"
	"strings"

	"github.com/Solher/auth-scaffold/domain"
	"github.com/Solher/auth-scaffold/interfaces"
	"github.com/Solher/auth-scaffold/internalerrors"
)

type SessionRepo struct {
	store interfaces.AbstractGormStore
	cache interfaces.AbstractLRUCacheStore
}

func NewSessionRepo(store interfaces.AbstractGormStore, cache interfaces.AbstractLRUCacheStore) *SessionRepo {
	return &SessionRepo{store: store, cache: cache}
}

func (r *SessionRepo) Create(sessions []domain.Session) ([]domain.Session, error) {
	db := r.store.GetDB()
	transaction := db.Begin()

	for i, session := range sessions {
		err := db.Create(&session).Error
		if err != nil {
			transaction.Rollback()

			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}

		sessions[i] = session
	}

	transaction.Commit()
	return sessions, nil
}

func (r *SessionRepo) CreateOne(session *domain.Session) (*domain.Session, error) {
	db := r.store.GetDB()

	err := db.Create(session).Error
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	return session, nil
}

func (r *SessionRepo) Find(filter *interfaces.Filter, ownerRelations []domain.Relation) ([]domain.Session, error) {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	sessions := []domain.Session{}

	err = query.Find(&sessions).Error
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return sessions, nil
}

func (r *SessionRepo) FindByID(id int, filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	session := domain.Session{}

	err = query.Where("sessions.id = ?", id).First(&session).Error
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return &session, nil
}

func (r *SessionRepo) Upsert(sessions []domain.Session, filter *interfaces.Filter, ownerRelations []domain.Relation) ([]domain.Session, error) {
	db := r.store.GetDB()
	transaction := db.Begin()

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	for i, session := range sessions {
		queryCopy := *query

		if session.ID != 0 {
			oldUser := domain.Session{}

			authToken := session.AuthToken

			err := queryCopy.Where("sessions.id = ?", session.ID).First(&oldUser).Updates(session).Error
			if err != nil {
				transaction.Rollback()

				if strings.Contains(err.Error(), "constraint") {
					return nil, internalerrors.NewViolatedConstraint(err.Error())
				}

				return nil, internalerrors.DatabaseError
			}

			err = r.cache.Remove(authToken)
			if err != nil {
				return nil, internalerrors.DatabaseError
			}

			err = r.cache.Add(session.AuthToken, session)
			if err != nil {
				return nil, internalerrors.DatabaseError
			}
		} else {
			err := db.Create(&session).Error
			if err != nil {
				transaction.Rollback()

				if strings.Contains(err.Error(), "constraint") {
					return nil, internalerrors.NewViolatedConstraint(err.Error())
				}

				return nil, internalerrors.DatabaseError
			}
		}

		sessions[i] = session
	}

	transaction.Commit()
	return sessions, nil
}

func (r *SessionRepo) UpsertOne(session *domain.Session, filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {
	db := r.store.GetDB()

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	if session.ID != 0 {
		oldUser := domain.Session{}

		authToken := session.AuthToken

		err := query.Where("sessions.id = ?", session.ID).First(&oldUser).Updates(session).Error
		if err != nil {
			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}

		err = r.cache.Remove(authToken)
		if err != nil {
			return nil, internalerrors.DatabaseError
		}

		err = r.cache.Add(session.AuthToken, session)
		if err != nil {
			return nil, internalerrors.DatabaseError
		}
	} else {
		err := db.Create(&session).Error
		if err != nil {
			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}
	}

	return session, nil
}

func (r *SessionRepo) UpdateByID(id int, session *domain.Session,
	filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	oldUser := domain.Session{}

	authToken := session.AuthToken

	err = query.Where("sessions.id = ?", id).First(&oldUser).Updates(session).Error
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	err = r.cache.Remove(authToken)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	err = r.cache.Add(session.AuthToken, session)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return session, nil
}

func (r *SessionRepo) DeleteAll(filter *interfaces.Filter, ownerRelations []domain.Relation) error {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = query.Delete(domain.Session{}).Error
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return internalerrors.DatabaseError
	}

	return nil
}

func (r *SessionRepo) DeleteByID(id int, filter *interfaces.Filter, ownerRelations []domain.Relation) error {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = query.Delete(&domain.Session{GormModel: domain.GormModel{ID: id}}).Error
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return internalerrors.DatabaseError
	}

	return nil
}

func (r *SessionRepo) Raw(query string, values ...interface{}) (*sql.Rows, error) {
	db := r.store.GetDB()

	rows, err := db.Raw(query, values...).Rows()
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return rows, nil
}
<commit_msg>Cache error handling fixed.<commit_after>// Generated by: main
// TypeWriter: repository
// Directive: +gen on Session

package ressources

import (
	"database/sql"
	"strings"

	"github.com/Solher/auth-scaffold/domain"
	"github.com/Solher/auth-scaffold/interfaces"
	"github.com/Solher/auth-scaffold/internalerrors"
)

type SessionRepo struct {
	store interfaces.AbstractGormStore
	cache interfaces.AbstractLRUCacheStore
}

func NewSessionRepo(store interfaces.AbstractGormStore, cache interfaces.AbstractLRUCacheStore) *SessionRepo {
	return &SessionRepo{store: store, cache: cache}
}

func (r *SessionRepo) Create(sessions []domain.Session) ([]domain.Session, error) {
	db := r.store.GetDB()
	transaction := db.Begin()

	for i, session := range sessions {
		err := db.Create(&session).Error
		if err != nil {
			transaction.Rollback()

			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}

		sessions[i] = session
	}

	transaction.Commit()
	return sessions, nil
}

func (r *SessionRepo) CreateOne(session *domain.Session) (*domain.Session, error) {
	db := r.store.GetDB()

	err := db.Create(session).Error
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	return session, nil
}

func (r *SessionRepo) Find(filter *interfaces.Filter, ownerRelations []domain.Relation) ([]domain.Session, error) {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	sessions := []domain.Session{}

	err = query.Find(&sessions).Error
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return sessions, nil
}

func (r *SessionRepo) FindByID(id int, filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	session := domain.Session{}

	err = query.Where("sessions.id = ?", id).First(&session).Error
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return &session, nil
}

func (r *SessionRepo) Upsert(sessions []domain.Session, filter *interfaces.Filter, ownerRelations []domain.Relation) ([]domain.Session, error) {
	db := r.store.GetDB()
	transaction := db.Begin()

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	for i, session := range sessions {
		queryCopy := *query

		if session.ID != 0 {
			oldUser := domain.Session{}

			authToken := session.AuthToken

			err := queryCopy.Where("sessions.id = ?", session.ID).First(&oldUser).Updates(session).Error
			if err != nil {
				transaction.Rollback()

				if strings.Contains(err.Error(), "constraint") {
					return nil, internalerrors.NewViolatedConstraint(err.Error())
				}

				return nil, internalerrors.DatabaseError
			}

			r.cache.Remove(authToken)
			err = r.cache.Add(session.AuthToken, session)
			if err != nil {
				return nil, internalerrors.DatabaseError
			}
		} else {
			err := db.Create(&session).Error
			if err != nil {
				transaction.Rollback()

				if strings.Contains(err.Error(), "constraint") {
					return nil, internalerrors.NewViolatedConstraint(err.Error())
				}

				return nil, internalerrors.DatabaseError
			}
		}

		sessions[i] = session
	}

	transaction.Commit()
	return sessions, nil
}

func (r *SessionRepo) UpsertOne(session *domain.Session, filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {
	db := r.store.GetDB()

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	if session.ID != 0 {
		oldUser := domain.Session{}

		authToken := session.AuthToken

		err := query.Where("sessions.id = ?", session.ID).First(&oldUser).Updates(session).Error
		if err != nil {
			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}

		r.cache.Remove(authToken)
		err = r.cache.Add(session.AuthToken, session)
		if err != nil {
			return nil, internalerrors.DatabaseError
		}
	} else {
		err := db.Create(&session).Error
		if err != nil {
			if strings.Contains(err.Error(), "constraint") {
				return nil, internalerrors.NewViolatedConstraint(err.Error())
			}

			return nil, internalerrors.DatabaseError
		}
	}

	return session, nil
}

func (r *SessionRepo) UpdateByID(id int, session *domain.Session,
	filter *interfaces.Filter, ownerRelations []domain.Relation) (*domain.Session, error) {

	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	oldUser := domain.Session{}

	authToken := session.AuthToken

	err = query.Where("sessions.id = ?", id).First(&oldUser).Updates(session).Error
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	r.cache.Remove(authToken)
	err = r.cache.Add(session.AuthToken, session)
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return session, nil
}

func (r *SessionRepo) DeleteAll(filter *interfaces.Filter, ownerRelations []domain.Relation) error {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = query.Delete(domain.Session{}).Error
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return internalerrors.DatabaseError
	}

	return nil
}

func (r *SessionRepo) DeleteByID(id int, filter *interfaces.Filter, ownerRelations []domain.Relation) error {
	query, err := r.store.BuildQuery(filter, ownerRelations)
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = query.Delete(&domain.Session{GormModel: domain.GormModel{ID: id}}).Error
	if err != nil {
		return internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return internalerrors.DatabaseError
	}

	return nil
}

func (r *SessionRepo) Raw(query string, values ...interface{}) (*sql.Rows, error) {
	db := r.store.GetDB()

	rows, err := db.Raw(query, values...).Rows()
	if err != nil {
		if strings.Contains(err.Error(), "constraint") {
			return nil, internalerrors.NewViolatedConstraint(err.Error())
		}

		return nil, internalerrors.DatabaseError
	}

	err = r.cache.Purge()
	if err != nil {
		return nil, internalerrors.DatabaseError
	}

	return rows, nil
}
<|endoftext|>


<commit_before>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"time"

	"gopkg.in/mgo.v2/bson"

	"gitlab.com/emreler/finch/auth"
	"gitlab.com/emreler/finch/channel"
	"gitlab.com/emreler/finch/logger"
	"gitlab.com/emreler/finch/models"
	"gitlab.com/emreler/finch/storage"
)

const (
	// TypeHTTP .
	TypeHTTP = "http"
)

// Handlers .
type Handlers struct {
	stg    *storage.Storage
	alt    *storage.Alerter
	logger *logger.Logger
	auth   *auth.Auth
}

// InitHandlers initializes handlers
func NewHandlers(stg *storage.Storage, alt *storage.Alerter, logger *logger.Logger, auth *auth.Auth) *Handlers {
	return &Handlers{stg: stg, alt: alt, logger: logger, auth: auth}
}

// CreateAlertRequest .
type CreateAlertRequest struct {
	Token       string `json:"token"`
	Name        string `json:"name"`
	Channel     string `json:"channel"`
	URL         string `json:"url"`
	Method      string `json:"method"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
	AlertDate   string `json:"alertDate"`
	AlertAfter  int    `json:"alertAfter"`
	RepeatEvery int    `json:"repeatEvery"`
}

// Validate validates request
func (r *CreateAlertRequest) Validate() error {
	if r.Channel == TypeHTTP {
		if match, _ := regexp.Match("^(http://|https://)", []byte(r.URL)); !match {
			return fmt.Errorf("url must be present in the http(s)://domain.com format")
		}

		if match, _ := regexp.Match("^(http://|https://)(localhost|127.0.0.1|172.17)", []byte(r.URL)); match {
			return fmt.Errorf("url can't be a local pointing address")
		}
	}
	return nil
}

// CreateAlertResponse .
type CreateAlertResponse struct {
	AlertDate string `json:"alertDate"`
}

// CreateUserRequest .
type CreateUserRequest struct {
	Name  *string `json:"name"`
	Email *string `json:"email"`
}

// CreateUserResponse .
type CreateUserResponse struct {
	Token   string `json:"token"`
	Expires int64  `json:"expires"`
}

// CreateAlert creates new alert
func (h *Handlers) Alerts(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	if r.Method == "POST" {
		req := &CreateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			h.logger.Error(err)
			return nil, err
		}

		var alertDate time.Time

		if req.AlertAfter != 0 {
			alertDate = time.Now().Add(time.Duration(req.AlertAfter) * time.Second)
		} else if req.AlertDate != "" {
			alertDate, err = time.Parse(time.RFC3339, req.AlertDate)

			if err != nil {
				return nil, fmt.Errorf("Invalid date format")
			}
		}

		alert := &models.Alert{
			Name:        req.Name,
			AlertDate:   alertDate,
			Channel:     req.Channel,
			URL:         req.URL,
			Method:      req.Method,
			ContentType: req.ContentType,
			Data:        req.Data,
			User:        bson.ObjectIdHex(userID),
		}

		if req.RepeatEvery > 0 {
			alert.Schedule = &models.Schedule{RepeatEvery: req.RepeatEvery}
		}

		alertID, err := h.stg.CreateAlert(alert)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		seconds := int(alertDate.Sub(time.Now()).Seconds())

		h.logger.Info(fmt.Sprintf("%d seconds later", seconds))

		h.alt.AddAlert(alertID, alertDate)

		res := &CreateAlertResponse{alertDate.Format(time.RFC3339)}
		return res, nil
	} else if r.Method == "GET" {

	} else {
		return nil, fmt.Errorf("Invalid method: %s", r.Method)
	}

	return nil, nil
}

// ProcessAlert processes the alert
func (h *Handlers) ProcessAlert(alertID string) {
	h.logger.Info(fmt.Sprintf("Getting %s", alertID))
	alert := h.stg.GetAlert(alertID)

	if alert.Channel == TypeHTTP {
		httpChannel := &channel.HttpChannel{}
		err := httpChannel.Notify(alert)

		if err != nil {
			h.logger.Info(fmt.Sprintf("Error while notifying with HTTP channel. %s", err.Error()))
		}

		if alert.Schedule != nil && alert.Schedule.RepeatEvery > 0 {
			nextAlertDate := time.Now().Add(time.Duration(alert.Schedule.RepeatEvery) * time.Second)
			h.logger.Info(fmt.Sprintf("Scheduling next alert %d seconds later at %s", alert.Schedule.RepeatEvery, nextAlertDate))
			h.alt.AddAlert(alertID, nextAlertDate)
		}
	}
}

// CreateUser .
func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	if r.Method == "POST" {
		req := &CreateUserRequest{}

		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&req)

		if err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if req.Name == nil || req.Email == nil {
			return nil, fmt.Errorf("Missing fields")
		}

		user := &models.User{Name: *req.Name, Email: *req.Email}

		userID, err := h.stg.CreateUser(user)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		exp := time.Now().Add(24 * 365 * time.Hour)
		tokenString, err := h.auth.GenerateToken(userID, exp)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &CreateUserResponse{Token: tokenString, Expires: exp.Unix()}
		return res, nil
	}

	return nil, fmt.Errorf("Invalid method: %s", r.Method)
}
<commit_msg>Fix storage return values<commit_after>package handlers

import (
	"encoding/json"
	"fmt"
	"net/http"
	"regexp"
	"time"

	"gopkg.in/mgo.v2/bson"

	"gitlab.com/emreler/finch/auth"
	"gitlab.com/emreler/finch/channel"
	"gitlab.com/emreler/finch/logger"
	"gitlab.com/emreler/finch/models"
	"gitlab.com/emreler/finch/storage"
)

const (
	// TypeHTTP .
	TypeHTTP = "http"
)

// Handlers .
type Handlers struct {
	stg    *storage.Storage
	alt    *storage.Alerter
	logger *logger.Logger
	auth   *auth.Auth
}

// InitHandlers initializes handlers
func NewHandlers(stg *storage.Storage, alt *storage.Alerter, logger *logger.Logger, auth *auth.Auth) *Handlers {
	return &Handlers{stg: stg, alt: alt, logger: logger, auth: auth}
}

// CreateAlertRequest .
type CreateAlertRequest struct {
	Token       string `json:"token"`
	Name        string `json:"name"`
	Channel     string `json:"channel"`
	URL         string `json:"url"`
	Method      string `json:"method"`
	ContentType string `json:"contentType"`
	Data        string `json:"data"`
	AlertDate   string `json:"alertDate"`
	AlertAfter  int    `json:"alertAfter"`
	RepeatEvery int    `json:"repeatEvery"`
}

// Validate validates request
func (r *CreateAlertRequest) Validate() error {
	if r.Channel == TypeHTTP {
		if match, _ := regexp.Match("^(http://|https://)", []byte(r.URL)); !match {
			return fmt.Errorf("url must be present in the http(s)://domain.com format")
		}

		if match, _ := regexp.Match("^(http://|https://)(localhost|127.0.0.1|172.17)", []byte(r.URL)); match {
			return fmt.Errorf("url can't be a local pointing address")
		}
	}
	return nil
}

// CreateAlertResponse .
type CreateAlertResponse struct {
	AlertDate string `json:"alertDate"`
}

// CreateUserRequest .
type CreateUserRequest struct {
	Name  *string `json:"name"`
	Email *string `json:"email"`
}

// CreateUserResponse .
type CreateUserResponse struct {
	Token   string `json:"token"`
	Expires int64  `json:"expires"`
}

// CreateAlert creates new alert
func (h *Handlers) Alerts(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	authorization := r.Header.Get("Authorization")

	re := regexp.MustCompile("Bearer (.*)")
	match := re.FindStringSubmatch(authorization)

	if len(match) != 2 {
		return nil, fmt.Errorf("No token found in requst")
	}

	tokenString := match[1]

	userID, err := h.auth.ValidateToken(tokenString)

	if err != nil {
		return nil, err
	}

	if r.Method == "POST" {
		req := &CreateAlertRequest{}

		decoder := json.NewDecoder(r.Body)

		if err = decoder.Decode(&req); err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if err = req.Validate(); err != nil {
			h.logger.Error(err)
			return nil, err
		}

		var alertDate time.Time

		if req.AlertAfter != 0 {
			alertDate = time.Now().Add(time.Duration(req.AlertAfter) * time.Second)
		} else if req.AlertDate != "" {
			alertDate, err = time.Parse(time.RFC3339, req.AlertDate)

			if err != nil {
				return nil, fmt.Errorf("Invalid date format")
			}
		}

		alert := &models.Alert{
			Name:        req.Name,
			AlertDate:   alertDate,
			Channel:     req.Channel,
			URL:         req.URL,
			Method:      req.Method,
			ContentType: req.ContentType,
			Data:        req.Data,
			User:        bson.ObjectIdHex(userID),
		}

		if req.RepeatEvery > 0 {
			alert.Schedule = &models.Schedule{RepeatEvery: req.RepeatEvery}
		}

		alertID, err := h.stg.CreateAlert(alert)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		seconds := int(alertDate.Sub(time.Now()).Seconds())

		h.logger.Info(fmt.Sprintf("%d seconds later", seconds))

		h.alt.AddAlert(alertID, alertDate)

		res := &CreateAlertResponse{alertDate.Format(time.RFC3339)}
		return res, nil
	} else if r.Method == "GET" {

	} else {
		return nil, fmt.Errorf("Invalid method: %s", r.Method)
	}

	return nil, nil
}

// ProcessAlert processes the alert
func (h *Handlers) ProcessAlert(alertID string) {
	h.logger.Info(fmt.Sprintf("Getting %s", alertID))
	alert, err := h.stg.GetAlert(alertID)

	if err != nil {
		h.logger.Error(err)
		return
	}

	if alert.Channel == TypeHTTP {
		httpChannel := &channel.HttpChannel{}
		err := httpChannel.Notify(alert)

		if err != nil {
			h.logger.Info(fmt.Sprintf("Error while notifying with HTTP channel. %s", err.Error()))
		}

		if alert.Schedule != nil && alert.Schedule.RepeatEvery > 0 {
			nextAlertDate := time.Now().Add(time.Duration(alert.Schedule.RepeatEvery) * time.Second)
			h.logger.Info(fmt.Sprintf("Scheduling next alert %d seconds later at %s", alert.Schedule.RepeatEvery, nextAlertDate))
			h.alt.AddAlert(alertID, nextAlertDate)
		}
	}
}

// CreateUser .
func (h *Handlers) CreateUser(w http.ResponseWriter, r *http.Request) (interface{}, error) {
	if r.Method == "POST" {
		req := &CreateUserRequest{}

		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&req)

		if err != nil {
			h.logger.Error(err)
			return nil, fmt.Errorf("Invalid format")
		}

		if req.Name == nil || req.Email == nil {
			return nil, fmt.Errorf("Missing fields")
		}

		user := &models.User{Name: *req.Name, Email: *req.Email}

		userID, err := h.stg.CreateUser(user)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		exp := time.Now().Add(24 * 365 * time.Hour)
		tokenString, err := h.auth.GenerateToken(userID, exp)

		if err != nil {
			h.logger.Error(err)
			return nil, err
		}

		res := &CreateUserResponse{Token: tokenString, Expires: exp.Unix()}
		return res, nil
	}

	return nil, fmt.Errorf("Invalid method: %s", r.Method)
}
<|endoftext|>