<commit_before>/*
Copyright 2016 Citrix Systems, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package netscaler

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
)

type NetscalerService struct {
	Name        string `json:"name"`
	Ip          string `json:"ip"`
	ServiceType string `json:"servicetype"`
	Port        int    `json:"port"`
}

type NetscalerLB struct {
	Name            string `json:"name"`
	Ipv46           string `json:"ipv46"`
	ServiceType     string `json:"servicetype"`
	Port            int    `json:"port"`
	PersistenceType string `json:"persistencetype,omitempty"`
	LbMethod        string `json:"lbmethod,omitempty"`
}

type NetscalerLBServiceBinding struct {
	Name        string `json:"name"`
	ServiceName string `json:"serviceName"`
}

type NetscalerCsAction struct {
	Name            string `json:"name"`
	TargetLBVserver string `json:"targetLBVserver"`
}

type NetscalerCsPolicy struct {
	PolicyName string `json:"policyName"`
	Rule       string `json:"rule"`
	Action     string `json:"action"`
}

type NetscalerCsPolicyBinding struct {
	Name       string `json:"name"`
	PolicyName string `json:"policyName"`
	Priority   int    `json:"priority"`
	Bindpoint  string `json:"bindpoint"`
}

type NetscalerCsVserver struct {
	Name        string `json:"name"`
	ServiceType string `json:"servicetype"`
	Ipv46       string `json:"ipv46"`
	Port        int    `json:"port"`
}

func (c *NitroClient) DeleteService(sname string) error {
	resourceType := "service"
	_, err := c.deleteResource(resourceType, sname)
	if err != nil {
		log.Println(fmt.Sprintf("Failed to delete service %s err=%s", sname, err))
		return err
	}
	return nil
}

func (c *NitroClient) CreateService(serviceStruct *NetscalerService) (string, error) {
	resourceType := "service"
	sname := serviceStruct.Name
	if !c.ResourceExists("service", sname) {
		if serviceStruct.ServiceType == "" {
			serviceStruct.ServiceType = "HTTP"
		}
		nsService := &struct {
			Service NetscalerService `json:"service"`
		}{Service: *serviceStruct}
		resourceJson, err := json.Marshal(nsService)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to marshal service %s err=", sname, err))
			return sname, err
		}
		log.Println(string(resourceJson))

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to create service %s err=%s", sname, err))
			return sname, err
		}
		log.Printf("Created service with name %s", sname)
		_ = body
	} else {
		log.Printf("Found service with name %s, not recreating", sname)
	}
	return sname, nil

}

func (c *NitroClient) AddAndBindService(lbName string, svcStruct *NetscalerService) error {
	_, err := c.CreateService(svcStruct)
	if err != nil {
		return err
	}
	sname := svcStruct.Name
	//bind the lb to the service
	resourceType := "lbvserver"
	boundResourceType := "service"
	if !c.ResourceBindingExists(resourceType, lbName, boundResourceType, "servicename", sname) {
		nsLbSvcBinding := &struct {
			Lbvserver_service_binding NetscalerLBServiceBinding `json:"lbvserver_service_binding"`
		}{Lbvserver_service_binding: NetscalerLBServiceBinding{Name: lbName, ServiceName: sname}}
		resourceJson, err := json.Marshal(nsLbSvcBinding)

		resourceType = "lbvserver_service_binding"

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to bind lb %s to service %s, err=%s", lbName, sname, err))
			_ = c.DeleteService(sname) //TODO: the problem might be that it is bound to a different lb
			return err
		}
		_ = body
	} else {
		log.Printf("lb %s already bound to service %s", lbName, sname)
	}
	return nil
}

func (c *NitroClient) CreateLBVserver(lbStruct *NetscalerLB) (string, error) {

	resourceType := "lbvserver"
	if c.ResourceExists(resourceType, lbStruct.Name) == false {
		if lbStruct.ServiceType == "" {
			lbStruct.ServiceType = "HTTP"
		}
		if lbStruct.Ipv46 == "" || lbStruct.Ipv46 == "0.0.0.0" {
			errstr := fmt.Sprintf("VIP cannot be empty or 0.0.0.0 for lb %s", lbStruct.Name)
			log.Fatal(errstr)
			return "", errors.New(errstr)
		}
		if lbStruct.Port == 0 && lbStruct.ServiceType == "HTTP" {
			lbStruct.Port = 80
		}
		if lbStruct.Port == 0 {
			errstr := fmt.Sprintf("Port cannot be 0 for lb %s", lbStruct.Name)
			log.Fatal(errstr)
			return "", errors.New(errstr)
		}

		nsLB := &struct {
			Lbvserver NetscalerLB `json:"lbvserver"`
		}{Lbvserver: *lbStruct}
		resourceJson, err := json.Marshal(nsLB)

		log.Println("Resourcejson is " + string(resourceJson))

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to create lb %s, err=%s", lbStruct.Name, err))
			//TODO roll back
			return "", err
		}
		_ = body
	}

	return lbStruct.Name, nil
}

func (c *NitroClient) DeleteResource(resourceType string, resourceName string) error {

	_, err := c.listResource(resourceType, resourceName)
	if err == nil { // resource exists
		log.Printf("Found resource of type %s: %s", resourceType, resourceName)
		_, err = c.deleteResource(resourceType, resourceName)
		if err != nil {
			log.Println(fmt.Sprintf("Failed to delete resourceType %: %s, err=%s", resourceType, resourceName, err))
			return err
		}
	} else {
		log.Printf("Resource %s already deleted ", resourceName)
	}
	return nil
}

func (c *NitroClient) DeleteLBVserver(lbName string) error {
	resourceType := "lbvserver"

	_, err := c.listResource(resourceType, lbName)
	if err == nil { // resource exists
		log.Printf("Found resource of type %s: %s", resourceType, lbName)
		_, err = c.deleteResource(resourceType, lbName)
		if err != nil {
			log.Println(fmt.Sprintf("Failed to delete lb %s, err=%s", lbName, err))
			return err
		}
	} else {
		log.Printf("Lb %s already deleted ", lbName)
	}<commit_msg>fix typo<commit_after>/*
Copyright 2016 Citrix Systems, Inc. All rights reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package netscaler

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"
)

type NetscalerService struct {
	Name        string `json:"name"`
	Ip          string `json:"ip"`
	ServiceType string `json:"servicetype"`
	Port        int    `json:"port"`
}

type NetscalerLB struct {
	Name            string `json:"name"`
	Ipv46           string `json:"ipv46"`
	ServiceType     string `json:"servicetype"`
	Port            int    `json:"port"`
	PersistenceType string `json:"persistencetype,omitempty"`
	LbMethod        string `json:"lbmethod,omitempty"`
}

type NetscalerLBServiceBinding struct {
	Name        string `json:"name"`
	ServiceName string `json:"serviceName"`
}

type NetscalerCsAction struct {
	Name            string `json:"name"`
	TargetLBVserver string `json:"targetLBVserver"`
}

type NetscalerCsPolicy struct {
	PolicyName string `json:"policyName"`
	Rule       string `json:"rule"`
	Action     string `json:"action"`
}

type NetscalerCsPolicyBinding struct {
	Name       string `json:"name"`
	PolicyName string `json:"policyName"`
	Priority   int    `json:"priority"`
	Bindpoint  string `json:"bindpoint"`
}

type NetscalerCsVserver struct {
	Name        string `json:"name"`
	ServiceType string `json:"servicetype"`
	Ipv46       string `json:"ipv46"`
	Port        int    `json:"port"`
}

func (c *NitroClient) DeleteService(sname string) error {
	resourceType := "service"
	_, err := c.deleteResource(resourceType, sname)
	if err != nil {
		log.Println(fmt.Sprintf("Failed to delete service %s err=%s", sname, err))
		return err
	}
	return nil
}

func (c *NitroClient) CreateService(serviceStruct *NetscalerService) (string, error) {
	resourceType := "service"
	sname := serviceStruct.Name
	if !c.ResourceExists("service", sname) {
		if serviceStruct.ServiceType == "" {
			serviceStruct.ServiceType = "HTTP"
		}
		nsService := &struct {
			Service NetscalerService `json:"service"`
		}{Service: *serviceStruct}
		resourceJson, err := json.Marshal(nsService)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to marshal service %s err=", sname, err))
			return sname, err
		}
		log.Println(string(resourceJson))

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to create service %s err=%s", sname, err))
			return sname, err
		}
		log.Printf("Created service with name %s", sname)
		_ = body
	} else {
		log.Printf("Found service with name %s, not recreating", sname)
	}
	return sname, nil

}

func (c *NitroClient) AddAndBindService(lbName string, svcStruct *NetscalerService) error {
	_, err := c.CreateService(svcStruct)
	if err != nil {
		return err
	}
	sname := svcStruct.Name
	//bind the lb to the service
	resourceType := "lbvserver"
	boundResourceType := "service"
	if !c.ResourceBindingExists(resourceType, lbName, boundResourceType, "servicename", sname) {
		nsLbSvcBinding := &struct {
			Lbvserver_service_binding NetscalerLBServiceBinding `json:"lbvserver_service_binding"`
		}{Lbvserver_service_binding: NetscalerLBServiceBinding{Name: lbName, ServiceName: sname}}
		resourceJson, err := json.Marshal(nsLbSvcBinding)

		resourceType = "lbvserver_service_binding"

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to bind lb %s to service %s, err=%s", lbName, sname, err))
			_ = c.DeleteService(sname) //TODO: the problem might be that it is bound to a different lb
			return err
		}
		_ = body
	} else {
		log.Printf("lb %s already bound to service %s", lbName, sname)
	}
	return nil
}

func (c *NitroClient) CreateLBVserver(lbStruct *NetscalerLB) (string, error) {

	resourceType := "lbvserver"
	if c.ResourceExists(resourceType, lbStruct.Name) == false {
		if lbStruct.ServiceType == "" {
			lbStruct.ServiceType = "HTTP"
		}
		if lbStruct.Ipv46 == "" || lbStruct.Ipv46 == "0.0.0.0" {
			errstr := fmt.Sprintf("VIP cannot be empty or 0.0.0.0 for lb %s", lbStruct.Name)
			log.Fatal(errstr)
			return "", errors.New(errstr)
		}
		if lbStruct.Port == 0 && lbStruct.ServiceType == "HTTP" {
			lbStruct.Port = 80
		}
		if lbStruct.Port == 0 {
			errstr := fmt.Sprintf("Port cannot be 0 for lb %s", lbStruct.Name)
			log.Fatal(errstr)
			return "", errors.New(errstr)
		}

		nsLB := &struct {
			Lbvserver NetscalerLB `json:"lbvserver"`
		}{Lbvserver: *lbStruct}
		resourceJson, err := json.Marshal(nsLB)

		log.Println("Resourcejson is " + string(resourceJson))

		body, err := c.createResource(resourceType, resourceJson)
		if err != nil {
			log.Fatal(fmt.Sprintf("Failed to create lb %s, err=%s", lbStruct.Name, err))
			//TODO roll back
			return "", err
		}
		_ = body
	}

	return lbStruct.Name, nil
}

func (c *NitroClient) DeleteResource(resourceType string, resourceName string) error {

	_, err := c.listResource(resourceType, resourceName)
	if err == nil { // resource exists
		log.Printf("Found resource of type %s: %s", resourceType, resourceName)
		_, err = c.deleteResource(resourceType, resourceName)
		if err != nil {
			log.Println(fmt.Sprintf("Failed to delete resourceType %s: %s, err=%s", resourceType, resourceName, err))
			return err
		}
	} else {
		log.Printf("Resource %s already deleted ", resourceName)
	}
	return nil
}

func (c *NitroClient) DeleteLBVserver(lbName string) error {
	resourceType := "lbvserver"

	_, err := c.listResource(resourceType, lbName)
	if err == nil { // resource exists
		log.Printf("Found resource of type %s: %s", resourceType, lbName)
		_, err = c.deleteResource(resourceType, lbName)
		if err != nil {
			log.Println(fmt.Sprintf("Failed to delete lb %s, err=%s", lbName, err))
			return err
		}
	} else {
		log.Printf("Lb %s already deleted ", lbName)
	}
{'fraction_non_alphanumeric': 0.12258887294755301, 'fraction_numerical': 0.0052606408417025345, 'mean_word_length': 4.051127214170692, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7206217', 'n_tokens_mistral': 4402, 'n_tokens_neox': 4082, 'n_words': 1168}