<commit_before>package apidef

const Schema = `{
    "type": ["object", "null"],
    "$schema": "http://json-schema.org/draft-04/schema",
    "id": "http://jsonschema.net",
    "additionalProperties": false,
    "properties": {
        "is_site": {
            "type": "boolean"
        },
        "uptime_tests": {
            "type": ["object", "null"]
        },
        "expire_analytics_after": {
            "type": "number"
        },
        "id": {
            "type": "string"
        },
        "org_id": {
            "type": "string"
        },
        "api_id": {
            "type": "string"
        },
        "enable_ip_whitelisting": {
            "type": "boolean"
        },
        "enable_ip_blacklisting": {
            "type": "boolean"
        },
        "enable_context_vars": {
            "type": "boolean"
        },
        "strip_auth_data": {
          "type": "boolean"
        },
        "do_not_track": {
            "type": "boolean"
        },
        "enable_jwt": {
            "type": "boolean"
        },
        "use_openid": {
            "type": "boolean"
        },
        "openid_options": {
            "type": ["object", "null"]
        },
        "use_standard_auth": {
            "type": "boolean"
        },
        "use_go_plugin_auth": {
            "type": "boolean"
        },
        "enable_coprocess_auth": {
            "type": "boolean"
        },
        "jwt_skip_kid": {
            "type": "boolean"
        },
        "base_identity_provided_by": {
            "type": "string"
        },
        "disable_rate_limit": {
            "type": "boolean"
        },
        "disable_quota": {
            "type": "boolean"
        },
        "custom_middleware_bundle": {
            "type": "string"
        },
        "jwt_policy_field_name": {
            "type": "string"
        },
        "jwt_default_policies": {
            "type": ["array", "null"]
        },
        "jwt_signing_method": {
            "type": "string"
        },
        "jwt_source": {
            "type": "string"
        },
        "jwt_identity_base_field": {
            "type": "string"
        },
        "jwt_client_base_field": {
            "type": "string"
        },
        "jwt_disable_issued_at_validation": {
            "type": "boolean"
        },
        "jwt_disable_expires_at_validation": {
            "type": "boolean"
        },
        "jwt_disable_not_before_validation": {
            "type": "boolean"
        },
        "jwt_issued_at_validation_skew": {
            "type": "number"
        },
        "jwt_expires_at_validation_skew": {
            "type": "number"
        },
        "jwt_not_before_validation_skew": {
            "type": "number"
        },
        "jwt_scope_to_policy_mapping": {
            "type": ["object", "null"]
        },
        "jwt_scope_claim_name": {
            "type": "string"
        },
        "use_keyless": {
            "type": "boolean"
        },
        "use_basic_auth": {
            "type": "boolean"
        },
        "use_mutual_tls_auth": {
            "type": "boolean"
        },
        "client_certificates": {
            "type": ["array", "null"]
        },
        "upstream_certificates": {
            "type": ["object", "null"]
        },
        "pinned_public_keys": {
            "type": ["object", "null"]
        },
        "allowed_ips": {
            "type": ["array", "null"]
        },
        "blacklisted_ips": {
            "type": ["array", "null"]
        },
        "enable_batch_request_support": {
            "type": "boolean"
        },
        "event_handlers": {
            "type":["object", "null"]
        },
        "notifications": {
            "type":["object", "null"]
        },
        "use_oauth2": {
            "type": "boolean"
        },
        "oauth_meta": {
            "type":["object", "null"]
        },
        "cache_options": {
            "type":["object", "null"]
        },
        "tags": {
            "type": ["array", "null"]
        },
        "tag_headers": {
            "type": ["array", "null"]
        },
        "basic_auth": {
            "type": ["object", "null"]
        },
        "CORS": {
            "type":["object", "null"]
        },
        "response_processors": {
            "type": ["array", "null"]
        },
        "auth_provider": {
            "type":["object", "null"],
            "properties": {
                "name": {
                    "type": "string",
                    "enum": [""]
                },
                "storage_engine": {
                    "type": "string",
                    "enum": [""]
                }
            }
        },
        "session_provider": {
            "type":["object", "null"],
            "properties": {
                "name": {
                    "type": "string",
                    "enum": [""]
                },
                "storage_engine": {
                    "type": "string",
                    "enum": [""]
                }
            }
        },
        "hmac_allowed_clock_skew": {
            "type": "number"
        },
        "hmac_allowed_algorithms": {
            "type": ["array", "null"]
        },
        "dont_set_quota_on_create": {
            "type": "boolean"
            },
        "custom_middleware": {
            "type":["object", "null"],
            "properties": {
                "pre": {
                    "type": ["array", "null"]
                },
                "post": {
                    "type": ["array", "null"]
                }
            }
        },
        "session_lifetime": {
            "type": "number"
        },
        "enable_detailed_recording": {
            "type": "boolean"
        },
        "enable_signature_checking": {
            "type": "boolean"
        },
        "active": {
            "type": "boolean"
        },
        "internal": {
            "type": "boolean"
        },
        "auth": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/auth",
            "properties": {
                "auth_header_name": {
                    "type": "string",
                    "id": "http://jsonschema.net/auth/auth_header_name"
                },
                "use_certificate": {
                    "type": "boolean"
                }
            }
        },
		"auth_configs":{
			"type": ["object", "null"]
		},
        "definition": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/definition",
            "properties": {
                "key": {
                    "type": "string",
                    "id": "http://jsonschema.net/definition/key"
                },
                "location": {
                    "type": "string",
                    "id": "http://jsonschema.net/definition/location"
                },
                "strip_path": {
                    "type": "boolean",
                    "id": "http://jsonschema.net/definition/location"
                }
            },
            "required": [
                "key",
                "location"
            ]
        },
        "name": {
            "type": "string",
            "id": "http://jsonschema.net/name"
        },
        "slug": {
            "type": "string",
            "pattern": "[a-zA-Z0-9]*",
            "id": "http://jsonschema.net/name"
        },
        "domain": {
            "type": "string"
        },
        "listen_port": {
            "type": "number"
        },
        "protocol": {
            "type": "string"
        },
        "enable_proxy_protocol": {
            "type": "boolean"
        },
        "certificates": {
            "type": ["array", "null"]
        },
        "check_host_against_uptime_tests": {
            "type": "boolean"
        },
        "proxy": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/proxy",
            "properties": {
                "target_url": {
                    "type": "string",
                    "id": "http://jsonschema.net/proxy/target_url"
                },
                "check_host_against_uptime_tests": {
                    "type": "boolean"
                },
                "preserve_host_header": {
                    "type": "boolean"
                },
                "transport": {
                    "type": ["object", "null"],
                    "properties": {
                        "ssl_ciphers": {
                            "type": ["array", "null"]
                        },
                        "ssl_min_version": {
                            "type": "number"
                        },
                        "proxy_url": {
                            "type": "string"
                        },
                        "ssl_force_common_name_check": {
                            "type": "boolean"
                        }
                    }
                }
            },
            "required": [
                "target_url"
            ]
        },
        "hook_references": {
            "type": ["object", "null"]
        },
        "version_data": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/version_data",
            "properties": {
                "not_versioned": {
                    "type": "boolean",
                    "id": "http://jsonschema.net/version_data/not_versioned"
                },
                "default_version":{
                    "type": "string",
                    "id": "http://jsonschema.net/version_data/default_version"
                },
                "versions": {
                    "type": ["object", "null"],
                    "id": "http://jsonschema.net/version_data/versions",
                    "patternProperties": {
                        "^[a-zA-Z0-9]+$": {
                            "title": "versionInfoProperty",
                            "type": ["object", "null"],
                            "id": "http://jsonschema.net/access_rights/versionInfoProperty",
                            "properties": {
                                "expires": {
                                    "type": "string",
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/expires"
                                },
                                "name": {
                                    "type": "string",
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/name"
                                },
                                "paths": {
                                    "type": ["object", "null"],
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths",
                                    "properties": {
                                        "black_list": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/black_list"
                                        },
                                        "ignored": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/ignored"
                                        },
                                        "white_list": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/white_list"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "name"
                            ]
                        }
                    }
                }
            },
            "required": [
                "not_versioned",
                "versions"
            ]
        },
        "config_data": {
            "type": ["object", "null"]
        },
        "global_rate_limit": {
          "type": ["object", "null"],
           "properties": {
                "rate": {
                    "type": "number"
                },
                "per": {
                    "type": "number"
                }
            }
        },
    "request_signing": {
          "type": ["object", "null"],
           "properties": {
                "is_enabled": {
                    "type": "boolean"
                },
                "secret": {
                    "type": "string"
                },
        "key_id": {
                    "type": "string"
                },
        "algorithm": {
                    "type": "string"
                }
            },
        "required": [
            "is_enabled"
        ]
        },
        "graphql": {
            "type": ["object", “null“],
            "properties": {
                "enabled": {
                    "type": "boolean"
                },
                "api": {
                    "type": "object",
                    "properties": {
                        "endpoint": {
                            "type": "string"
                        },
                        "schema": {
                            "type": "string"
                        },
                        "execution": {
                            "type": "object",
                            "properties": {
                                "mode": {
                                    "type": "string",
                                    "enum": ["proxyOnly"]
                                },
                                "validation": {
                                    "type": "object",
                                    "properties": {
                                        "enabled": {
                                            "type": "boolean"
                                        },
                                        "on_fail": {
                                            "type": "string",
                                            "enum": ["httpStatusCode400", "useErrorObject"]
                                        }
                                    },
                                    "required": [
                                        "enabled",
                                        "on_fail"
                                    ]
                                }
                            },
                            "required": [
                                "mode",
                                "validation"
                            ]
                        }
                    },
                    "required": [
                        "endpoint",
                        "schema",
                        "execution"
                    ]
                },
                "playground": {
                    "type": "object",
                    "properties": {
                        "enabled": {
                            "type": "boolean"
                        },
                        "path": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "enabled"
                    ]
                }
            },
            "required": [
                "enabled"
            ]
        }
    },
    "required": [
        "auth",
        "name",
        "proxy",
        "version_data"
    ]
}`
<commit_msg>Fix schema issue<commit_after>package apidef

const Schema = `{
    "type": ["object", "null"],
    "$schema": "http://json-schema.org/draft-04/schema",
    "id": "http://jsonschema.net",
    "additionalProperties": false,
    "properties": {
        "is_site": {
            "type": "boolean"
        },
        "uptime_tests": {
            "type": ["object", "null"]
        },
        "expire_analytics_after": {
            "type": "number"
        },
        "id": {
            "type": "string"
        },
        "org_id": {
            "type": "string"
        },
        "api_id": {
            "type": "string"
        },
        "enable_ip_whitelisting": {
            "type": "boolean"
        },
        "enable_ip_blacklisting": {
            "type": "boolean"
        },
        "enable_context_vars": {
            "type": "boolean"
        },
        "strip_auth_data": {
          "type": "boolean"
        },
        "do_not_track": {
            "type": "boolean"
        },
        "enable_jwt": {
            "type": "boolean"
        },
        "use_openid": {
            "type": "boolean"
        },
        "openid_options": {
            "type": ["object", "null"]
        },
        "use_standard_auth": {
            "type": "boolean"
        },
        "use_go_plugin_auth": {
            "type": "boolean"
        },
        "enable_coprocess_auth": {
            "type": "boolean"
        },
        "jwt_skip_kid": {
            "type": "boolean"
        },
        "base_identity_provided_by": {
            "type": "string"
        },
        "disable_rate_limit": {
            "type": "boolean"
        },
        "disable_quota": {
            "type": "boolean"
        },
        "custom_middleware_bundle": {
            "type": "string"
        },
        "jwt_policy_field_name": {
            "type": "string"
        },
        "jwt_default_policies": {
            "type": ["array", "null"]
        },
        "jwt_signing_method": {
            "type": "string"
        },
        "jwt_source": {
            "type": "string"
        },
        "jwt_identity_base_field": {
            "type": "string"
        },
        "jwt_client_base_field": {
            "type": "string"
        },
        "jwt_disable_issued_at_validation": {
            "type": "boolean"
        },
        "jwt_disable_expires_at_validation": {
            "type": "boolean"
        },
        "jwt_disable_not_before_validation": {
            "type": "boolean"
        },
        "jwt_issued_at_validation_skew": {
            "type": "number"
        },
        "jwt_expires_at_validation_skew": {
            "type": "number"
        },
        "jwt_not_before_validation_skew": {
            "type": "number"
        },
        "jwt_scope_to_policy_mapping": {
            "type": ["object", "null"]
        },
        "jwt_scope_claim_name": {
            "type": "string"
        },
        "use_keyless": {
            "type": "boolean"
        },
        "use_basic_auth": {
            "type": "boolean"
        },
        "use_mutual_tls_auth": {
            "type": "boolean"
        },
        "client_certificates": {
            "type": ["array", "null"]
        },
        "upstream_certificates": {
            "type": ["object", "null"]
        },
        "pinned_public_keys": {
            "type": ["object", "null"]
        },
        "allowed_ips": {
            "type": ["array", "null"]
        },
        "blacklisted_ips": {
            "type": ["array", "null"]
        },
        "enable_batch_request_support": {
            "type": "boolean"
        },
        "event_handlers": {
            "type":["object", "null"]
        },
        "notifications": {
            "type":["object", "null"]
        },
        "use_oauth2": {
            "type": "boolean"
        },
        "oauth_meta": {
            "type":["object", "null"]
        },
        "cache_options": {
            "type":["object", "null"]
        },
        "tags": {
            "type": ["array", "null"]
        },
        "tag_headers": {
            "type": ["array", "null"]
        },
        "basic_auth": {
            "type": ["object", "null"]
        },
        "CORS": {
            "type":["object", "null"]
        },
        "response_processors": {
            "type": ["array", "null"]
        },
        "auth_provider": {
            "type":["object", "null"],
            "properties": {
                "name": {
                    "type": "string",
                    "enum": [""]
                },
                "storage_engine": {
                    "type": "string",
                    "enum": [""]
                }
            }
        },
        "session_provider": {
            "type":["object", "null"],
            "properties": {
                "name": {
                    "type": "string",
                    "enum": [""]
                },
                "storage_engine": {
                    "type": "string",
                    "enum": [""]
                }
            }
        },
        "hmac_allowed_clock_skew": {
            "type": "number"
        },
        "hmac_allowed_algorithms": {
            "type": ["array", "null"]
        },
        "dont_set_quota_on_create": {
            "type": "boolean"
            },
        "custom_middleware": {
            "type":["object", "null"],
            "properties": {
                "pre": {
                    "type": ["array", "null"]
                },
                "post": {
                    "type": ["array", "null"]
                }
            }
        },
        "session_lifetime": {
            "type": "number"
        },
        "enable_detailed_recording": {
            "type": "boolean"
        },
        "enable_signature_checking": {
            "type": "boolean"
        },
        "active": {
            "type": "boolean"
        },
        "internal": {
            "type": "boolean"
        },
        "auth": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/auth",
            "properties": {
                "auth_header_name": {
                    "type": "string",
                    "id": "http://jsonschema.net/auth/auth_header_name"
                },
                "use_certificate": {
                    "type": "boolean"
                }
            }
        },
		"auth_configs":{
			"type": ["object", "null"]
		},
        "definition": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/definition",
            "properties": {
                "key": {
                    "type": "string",
                    "id": "http://jsonschema.net/definition/key"
                },
                "location": {
                    "type": "string",
                    "id": "http://jsonschema.net/definition/location"
                },
                "strip_path": {
                    "type": "boolean",
                    "id": "http://jsonschema.net/definition/location"
                }
            },
            "required": [
                "key",
                "location"
            ]
        },
        "name": {
            "type": "string",
            "id": "http://jsonschema.net/name"
        },
        "slug": {
            "type": "string",
            "pattern": "[a-zA-Z0-9]*",
            "id": "http://jsonschema.net/name"
        },
        "domain": {
            "type": "string"
        },
        "listen_port": {
            "type": "number"
        },
        "protocol": {
            "type": "string"
        },
        "enable_proxy_protocol": {
            "type": "boolean"
        },
        "certificates": {
            "type": ["array", "null"]
        },
        "check_host_against_uptime_tests": {
            "type": "boolean"
        },
        "proxy": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/proxy",
            "properties": {
                "target_url": {
                    "type": "string",
                    "id": "http://jsonschema.net/proxy/target_url"
                },
                "check_host_against_uptime_tests": {
                    "type": "boolean"
                },
                "preserve_host_header": {
                    "type": "boolean"
                },
                "transport": {
                    "type": ["object", "null"],
                    "properties": {
                        "ssl_ciphers": {
                            "type": ["array", "null"]
                        },
                        "ssl_min_version": {
                            "type": "number"
                        },
                        "proxy_url": {
                            "type": "string"
                        },
                        "ssl_force_common_name_check": {
                            "type": "boolean"
                        }
                    }
                }
            },
            "required": [
                "target_url"
            ]
        },
        "hook_references": {
            "type": ["object", "null"]
        },
        "version_data": {
            "type": ["object", "null"],
            "id": "http://jsonschema.net/version_data",
            "properties": {
                "not_versioned": {
                    "type": "boolean",
                    "id": "http://jsonschema.net/version_data/not_versioned"
                },
                "default_version":{
                    "type": "string",
                    "id": "http://jsonschema.net/version_data/default_version"
                },
                "versions": {
                    "type": ["object", "null"],
                    "id": "http://jsonschema.net/version_data/versions",
                    "patternProperties": {
                        "^[a-zA-Z0-9]+$": {
                            "title": "versionInfoProperty",
                            "type": ["object", "null"],
                            "id": "http://jsonschema.net/access_rights/versionInfoProperty",
                            "properties": {
                                "expires": {
                                    "type": "string",
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/expires"
                                },
                                "name": {
                                    "type": "string",
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/name"
                                },
                                "paths": {
                                    "type": ["object", "null"],
                                    "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths",
                                    "properties": {
                                        "black_list": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/black_list"
                                        },
                                        "ignored": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/ignored"
                                        },
                                        "white_list": {
                                            "type": ["array", "null"],
                                            "id": "http://jsonschema.net/version_data/versions/versionInfoProperty/paths/white_list"
                                        }
                                    }
                                }
                            },
                            "required": [
                                "name"
                            ]
                        }
                    }
                }
            },
            "required": [
                "not_versioned",
                "versions"
            ]
        },
        "config_data": {
            "type": ["object", "null"]
        },
        "global_rate_limit": {
          "type": ["object", "null"],
           "properties": {
                "rate": {
                    "type": "number"
                },
                "per": {
                    "type": "number"
                }
            }
        },
    "request_signing": {
          "type": ["object", "null"],
           "properties": {
                "is_enabled": {
                    "type": "boolean"
                },
                "secret": {
                    "type": "string"
                },
        "key_id": {
                    "type": "string"
                },
        "algorithm": {
                    "type": "string"
                }
            },
        "required": [
            "is_enabled"
        ]
        },
        "graphql": {
            "type": ["object", "null"],
            "properties": {
                "enabled": {
                    "type": "boolean"
                },
                "api": {
                    "type": "object",
                    "properties": {
                        "endpoint": {
                            "type": "string"
                        },
                        "schema": {
                            "type": "string"
                        },
                        "execution": {
                            "type": "object",
                            "properties": {
                                "mode": {
                                    "type": "string",
                                    "enum": ["proxyOnly"]
                                },
                                "validation": {
                                    "type": "object",
                                    "properties": {
                                        "enabled": {
                                            "type": "boolean"
                                        },
                                        "on_fail": {
                                            "type": "string",
                                            "enum": ["httpStatusCode400", "useErrorObject"]
                                        }
                                    },
                                    "required": [
                                        "enabled",
                                        "on_fail"
                                    ]
                                }
                            },
                            "required": [
                                "mode",
                                "validation"
                            ]
                        }
                    },
                    "required": [
                        "endpoint",
                        "schema",
                        "execution"
                    ]
                },
                "playground": {
                    "type": "object",
                    "properties": {
                        "enabled": {
                            "type": "boolean"
                        },
                        "path": {
                            "type": "string"
                        }
                    },
                    "required": [
                        "enabled"
                    ]
                }
            },
            "required": [
                "enabled"
            ]
        }
    },
    "required": [
        "auth",
        "name",
        "proxy",
        "version_data"
    ]
}`
<|endoftext|>


<commit_before>// Package profile is for specific profiles
package profile

// Local is a profile for local environments
func Local() []string {
	return []string{}
}

// Kubernetes is a profile for kubernetes
func Kubernetes() []string {
	return []string{}
}

// Platform is a platform profile
func Platform() []string {
	return []string{
		"MICRO_BROKER=service",
		"MICRO_REGISTRY=service",
		"MICRO_STORE=service",
		"MICRO_PROXY=go.micro.proxy",
		// expects k8s service name
		"MICRO_PROXY_ADDRESS=micro-proxy:8081",
	}
}
<commit_msg>Runtime Profile (#538)<commit_after>// Package profile is for specific profiles
package profile

// Local is a profile for local environments
func Local() []string {
	return []string{}
}

// Kubernetes is a profile for kubernetes
func Kubernetes() []string {
	return []string{}
}

// Platform is a platform profile
func Platform() []string {
	return []string{
		"MICRO_AUTH=service",
		"MICRO_STORE=service",
		"MICRO_BROKER=service",
		"MICRO_RUNTIME=service",
		"MICRO_REGISTRY=service",
		// micro proxy routes all requests
		// and expects a k8s service name
		"MICRO_PROXY=go.micro.proxy",
		"MICRO_PROXY_ADDRESS=micro-proxy:8081",
	}
}
<|endoftext|>


<commit_before>package protocol

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
)

// This is sent into the function
// All HTTP request headers should be set in env
type JSONIO struct {
	Headers    http.Header `json:"headers,omitempty"`
	Body       string      `json:"body"`
	StatusCode int         `json:"status_code,omitempty"`
}

// JSONProtocol converts stdin/stdout streams from HTTP into JSON format.
type JSONProtocol struct {
	in  io.Writer
	out io.Reader
}

func (p *JSONProtocol) IsStreamable() bool {
	return true
}

type RequestEncoder struct {
	*json.Encoder
}

func (h *JSONProtocol) DumpJSON(w io.Writer, req *http.Request) error {
	stdin := json.NewEncoder(h.in)
	_, err := io.WriteString(h.in, `{`)
	if err != nil {
		// this shouldn't happen
		return err
	}

	if req.ContentLength != 0 {
		_, err := io.WriteString(h.in, `"body": `)
		if err != nil {
			// this shouldn't happen
			return err
		}
		bb := new(bytes.Buffer)
		_, err = bb.ReadFrom(req.Body)
		if err != nil {
			return err
		}

		err = stdin.Encode(bb.String())
		if err != nil {
			return err
		}
		_, err = io.WriteString(h.in, `,`)
		if err != nil {
			// this shouldn't happen
			return err
		}
		defer bb.Reset()
	}
	_, err = io.WriteString(h.in, `"headers:"`)
	if err != nil {
		// this shouldn't happen
		return err
	}
	err = stdin.Encode(req.Header)
	if err != nil {
		// this shouldn't happen
		return err
	}
	_, err = io.WriteString(h.in, `"}`)
	if err != nil {
		// this shouldn't happen
		return err
	}
	return nil
}

func (h *JSONProtocol) Dispatch(w io.Writer, req *http.Request) error {
	err := h.DumpJSON(w, req)
	if err != nil {
		return err
	}
	jout := new(JSONIO)
	dec := json.NewDecoder(h.out)
	if err := dec.Decode(jout); err != nil {
		return err
	}
	if rw, ok := w.(http.ResponseWriter); ok {
		// this has to be done for pulling out:
		// - status code
		// - body
		// - headers
		for k, vs := range jout.Headers {
			for _, v := range vs {
				rw.Header().Add(k, v) // on top of any specified on the route
			}
		}
		rw.WriteHeader(jout.StatusCode)
		_, err = io.WriteString(rw, jout.Body) // TODO timeout
		if err != nil {
			return err
		}
	} else {
		// logs can just copy the full thing in there, headers and all.
		err = json.NewEncoder(w).Encode(jout)
		if err != nil {
			return err
		}
	}
	return nil
}
<commit_msg>Read request body and see if it's not empty then decide whether write it or not<commit_after>package protocol

import (
	"bytes"
	"encoding/json"
	"io"
	"net/http"
)

// This is sent into the function
// All HTTP request headers should be set in env
type JSONIO struct {
	Headers    http.Header `json:"headers,omitempty"`
	Body       string      `json:"body"`
	StatusCode int         `json:"status_code,omitempty"`
}

// JSONProtocol converts stdin/stdout streams from HTTP into JSON format.
type JSONProtocol struct {
	in  io.Writer
	out io.Reader
}

func (p *JSONProtocol) IsStreamable() bool {
	return true
}

type RequestEncoder struct {
	*json.Encoder
}

func (h *JSONProtocol) DumpJSON(w io.Writer, req *http.Request) error {
	stdin := json.NewEncoder(h.in)
	_, err := io.WriteString(h.in, `{`)
	if err != nil {
		// this shouldn't happen
		return err
	}

	bb := new(bytes.Buffer)
	_, err = bb.ReadFrom(req.Body)
	if err != nil {
		return err
	}
	reqData := bb.String()
	if reqData != "" {
		_, err := io.WriteString(h.in, `"body": `)
		if err != nil {
			// this shouldn't happen
			return err
		}
		err = stdin.Encode(reqData)
		if err != nil {
			return err
		}
		_, err = io.WriteString(h.in, `,`)
		if err != nil {
			// this shouldn't happen
			return err
		}
		defer bb.Reset()
	}
	_, err = io.WriteString(h.in, `"headers:"`)
	if err != nil {
		// this shouldn't happen
		return err
	}
	err = stdin.Encode(req.Header)
	if err != nil {
		// this shouldn't happen
		return err
	}
	_, err = io.WriteString(h.in, `"}`)
	if err != nil {
		// this shouldn't happen
		return err
	}
	return nil
}

func (h *JSONProtocol) Dispatch(w io.Writer, req *http.Request) error {
	err := h.DumpJSON(w, req)
	if err != nil {
		return err
	}
	jout := new(JSONIO)
	dec := json.NewDecoder(h.out)
	if err := dec.Decode(jout); err != nil {
		return err
	}
	if rw, ok := w.(http.ResponseWriter); ok {
		// this has to be done for pulling out:
		// - status code
		// - body
		// - headers
		for k, vs := range jout.Headers {
			for _, v := range vs {
				rw.Header().Add(k, v) // on top of any specified on the route
			}
		}
		rw.WriteHeader(jout.StatusCode)
		_, err = io.WriteString(rw, jout.Body) // TODO timeout
		if err != nil {
			return err
		}
	} else {
		// logs can just copy the full thing in there, headers and all.
		err = json.NewEncoder(w).Encode(jout)
		if err != nil {
			return err
		}
	}
	return nil
}
<|endoftext|>


<commit_before>package playground

import (
	"sync"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/ivan1993spb/snake-server/concurrent-map"
	"github.com/ivan1993spb/snake-server/engine"
)

func Test_Playground_CreateObject(t *testing.T) {
	object := &struct{}{}
	location := engine.Location{engine.Dot{0, 0}}

	pg, err := NewPlayground(100, 100)
	require.Nil(t, err)

	err = pg.CreateObject(object, location)
	require.Nil(t, err)
}

func Test_Playground_CreateObjectRandomRect(t *testing.T) {
	object := &struct{}{}

	pg, err := NewPlayground(100, 100)
	require.Nil(t, err)

	location, err := pg.CreateObjectRandomRect(object, 10, 10)
	require.Nil(t, err)
	require.Len(t, location, 100)
}

func Test_Playground_UpdateObject(t *testing.T) {
	t.SkipNow()
}

func Benchmark_Playground_UpdateObject(b *testing.B) {
	// TODO: Implement benchmark.
}

func Test_Playground_DeleteObject(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct{}{}

	pg.cMap.MSet(prepareMap(object, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	err := pg.DeleteObject(object, engine.Location{{1, 1}})
	require.Nil(t, err)

	require.Empty(t, pg.objects)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
}

func Test_Playground_CreateObjectAvailableDots_EmptyScene(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_CreateObjectAvailableDots_LocationNotAvailable(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_CreateObjectAvailableDots_LocationsIntersects(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_UpdateObjectAvailableDots_EmptyMap(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct{}{}

	pg.cMap.MSet(prepareMap(object, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	location, err := pg.UpdateObjectAvailableDots(object, engine.Location{{1, 1}}, engine.Location{{1, 2}})
	require.Nil(t, err)
	require.Equal(t, engine.Location{{1, 2}}, location)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 2}}.Hash()))
}

func Test_Playground_UpdateObjectAvailableDots_NotEmptyMap(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object1 := &struct {
		data string
	}{"first"}

	pg.cMap.MSet(prepareMap(object1, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object1)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	object2 := &struct {
		data string
	}{"second"}

	pg.cMap.MSet(prepareMap(object2, engine.Location{{1, 3}}))
	pg.objects = append(pg.objects, object2)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 3}}.Hash()))

	location, err := pg.UpdateObjectAvailableDots(object1, engine.Location{{1, 1}}, engine.Location{{1, 2}})
	require.Nil(t, err)
	require.Equal(t, engine.Location{{1, 2}}, location)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 2}}.Hash()))
}
<commit_msg>Create tests for playground.Playground<commit_after>package playground

import (
	"sync"
	"testing"

	"github.com/stretchr/testify/require"

	"github.com/ivan1993spb/snake-server/concurrent-map"
	"github.com/ivan1993spb/snake-server/engine"
)

func Test_NewPlayground_CreatesPlayground(t *testing.T) {
	tests := []struct {
		width, height uint8
	}{
		{
			width:  200,
			height: 100,
		},
		{
			width:  80,
			height: 100,
		},
		{
			width:  30,
			height: 22,
		},
		{
			width:  255,
			height: 200,
		},
	}

	for i, test := range tests {
		pg, err := NewPlayground(test.width, test.height)
		require.Nil(t, err, "test %d", i)
		require.NotNil(t, pg, "test %d", i)
		require.Equal(t, test.width, pg.area.Width(), "test %d", i)
		require.Equal(t, test.height, pg.area.Height(), "test %d", i)
		require.Equal(t, uint16(test.width)*uint16(test.height), pg.area.Size(), "test %d", i)
	}
}

func Test_Playground_CreateObject(t *testing.T) {
	object := &struct {
		a int
	}{
		10,
	}
	location := engine.Location{engine.Dot{0, 0}}

	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	err := pg.CreateObject(object, location)
	require.Nil(t, err)
	require.Len(t, pg.objects, 1)
	require.Equal(t, object, pg.objects[0])
	actual, ok := pg.cMap.Get(engine.Dot{0, 0}.Hash())
	require.True(t, ok)
	require.Equal(t, object, actual)
}

func Test_Playground_CreateObjectRandomRect(t *testing.T) {
	object := &struct {
		str string
	}{
		"ok",
	}

	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	location, err := pg.CreateObjectRandomRect(object, 10, 10)
	require.Nil(t, err)
	require.Len(t, location, 100)

	for _, dot := range location {
		require.True(t, pg.cMap.Has(dot.Hash()))
		actual, ok := pg.cMap.Get(dot.Hash())
		require.True(t, ok)
		require.Equal(t, object, actual)
	}
}

func Test_Playground_UpdateObject(t *testing.T) {
	t.SkipNow()
}

func Benchmark_Playground_UpdateObject(b *testing.B) {
	// TODO: Implement benchmark.
}

func Test_Playground_DeleteObject(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct{}{}

	pg.cMap.MSet(prepareMap(object, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	err := pg.DeleteObject(object, engine.Location{{1, 1}})
	require.Nil(t, err)

	require.Empty(t, pg.objects)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
}

func Test_Playground_CreateObjectAvailableDots_EmptyScene(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_CreateObjectAvailableDots_LocationNotAvailable(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_CreateObjectAvailableDots_LocationsIntersects(t *testing.T) {
	t.SkipNow()
	// TODO: Implement test.
}

func Test_Playground_UpdateObjectAvailableDots_EmptyMap(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct{}{}

	pg.cMap.MSet(prepareMap(object, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	location, err := pg.UpdateObjectAvailableDots(object, engine.Location{{1, 1}}, engine.Location{{1, 2}})
	require.Nil(t, err)
	require.Equal(t, engine.Location{{1, 2}}, location)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 2}}.Hash()))
}

func Test_Playground_UpdateObjectAvailableDots_NotEmptyMap(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object1 := &struct {
		data string
	}{"first"}

	pg.cMap.MSet(prepareMap(object1, engine.Location{{1, 1}}))
	pg.objects = append(pg.objects, object1)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))

	object2 := &struct {
		data string
	}{"second"}

	pg.cMap.MSet(prepareMap(object2, engine.Location{{1, 3}}))
	pg.objects = append(pg.objects, object2)

	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 3}}.Hash()))

	location, err := pg.UpdateObjectAvailableDots(object1, engine.Location{{1, 1}}, engine.Location{{1, 2}})
	require.Nil(t, err)
	require.Equal(t, engine.Location{{1, 2}}, location)
	require.Empty(t, pg.cMap.MGet(engine.Location{{1, 1}}.Hash()))
	require.NotEmpty(t, pg.cMap.MGet(engine.Location{{1, 2}}.Hash()))
}

func Test_Playground_UpdateObjectAvailableDots_NotEmptyMap_BigObjects(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object1 := &struct {
		data string
	}{"first"}
	location1Old := engine.Location{
		{1, 1},
		{1, 2},
		{1, 3},
		{1, 4},
		{1, 5},
		{1, 6},
	}
	location1New := engine.Location{
		{2, 0},
		{2, 1},
		{2, 2},
		{1, 3},
		{1, 4},
		{1, 5},
		{3, 6},
		{3, 6},
	}
	location1Expected := engine.Location{
		{2, 0},
		{1, 3},
		{1, 4},
		{1, 5},
		{3, 6},
	}

	pg.cMap.MSet(prepareMap(object1, location1Old))
	pg.objects = append(pg.objects, object1)
	for _, dot := range location1Old {
		require.True(t, pg.cMap.Has(dot.Hash()))
		actual, ok := pg.cMap.Get(dot.Hash())
		require.True(t, ok)
		require.Equal(t, object1, actual)
	}

	object2 := &struct {
		data string
	}{"second"}
	location2 := engine.Location{
		{2, 1},
		{2, 2},
		{2, 3},
		{2, 4},
		{2, 5},
		{2, 6},
	}

	pg.cMap.MSet(prepareMap(object2, location2))
	pg.objects = append(pg.objects, object2)
	for _, dot := range location2 {
		require.True(t, pg.cMap.Has(dot.Hash()))
		actual, ok := pg.cMap.Get(dot.Hash())
		require.True(t, ok)
		require.Equal(t, object2, actual)
	}

	location1Actual, err := pg.UpdateObjectAvailableDots(object1, location1Old, location1New)
	require.Nil(t, err)
	require.True(t, location1Expected.Equals(location1Actual))

	for _, dot := range pg.area.Dots() {
		actualObject, ok := pg.cMap.Get(dot.Hash())

		if location1Expected.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object1, actualObject, "dot %s", dot)
		} else if location2.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object2, actualObject, "dot %s", dot)
		} else {
			require.False(t, ok, "dot %s", dot)
			require.Nil(t, actualObject, "dot %s", dot)
		}
	}
}

func Test_Playground_CreateObjectRandomDot_SquareEmptyPlayground(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct {
		data string
	}{"first"}

	location, err := pg.CreateObjectRandomDot(object)
	require.Nil(t, err)
	require.Len(t, location, 1)

	for _, dot := range pg.area.Dots() {
		actualObject, ok := pg.cMap.Get(dot.Hash())

		if location.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object, actualObject, "dot %s", dot)
		} else {
			require.False(t, ok, "dot %s", dot)
			require.Nil(t, actualObject, "dot %s", dot)
		}
	}
}

func Test_Playground_CreateObjectRandomDot_EmptyPlayground(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(200, 100),
	}

	object := &struct {
		data string
	}{"first"}

	location, err := pg.CreateObjectRandomDot(object)
	require.Nil(t, err)
	require.Len(t, location, 1)

	for _, dot := range pg.area.Dots() {
		actualObject, ok := pg.cMap.Get(dot.Hash())

		if location.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object, actualObject, "dot %s", dot)
		} else {
			require.False(t, ok, "dot %s", dot)
			require.Nil(t, actualObject, "dot %s", dot)
		}
	}
}

func Test_Playground_CreateObjectRandomRect_SquareEmptyPlayground_SquareRect(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct {
		data string
	}{"first"}

	location, err := pg.CreateObjectRandomRect(object, 10, 10)
	require.Nil(t, err)
	require.Len(t, location, 10*10)

	for _, dot := range pg.area.Dots() {
		actualObject, ok := pg.cMap.Get(dot.Hash())

		if location.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object, actualObject, "dot %s", dot)
		} else {
			require.False(t, ok, "dot %s", dot)
			require.Nil(t, actualObject, "dot %s", dot)
		}
	}
}

func Test_Playground_CreateObjectRandomRect_SquareEmptyPlayground(t *testing.T) {
	pg := &Playground{
		cMap:       cmap.NewDefault(),
		objects:    make([]interface{}, 0),
		objectsMux: &sync.RWMutex{},
		area:       engine.MustArea(100, 100),
	}

	object := &struct {
		data string
	}{"first"}

	location, err := pg.CreateObjectRandomRect(object, 10, 8)
	require.Nil(t, err)
	require.Len(t, location, 10*8)

	for _, dot := range pg.area.Dots() {
		actualObject, ok := pg.cMap.Get(dot.Hash())

		if location.Contains(dot) {
			require.True(t, ok, "dot %s", dot)
			require.Equal(t, object, actualObject, "dot %s", dot)
		} else {
			require.False(t, ok, "dot %s", dot)
			require.Nil(t, actualObject, "dot %s", dot)
		}
	}
}
<|endoftext|>


<commit_before>package db

import (
	"database/sql"
	"github.com/go-sql-driver/mysql"
	"time"
)

type Follow struct {
	id           int
	UserId       int64
	UserName     string
	Status       string
	FollowDate   time.Time
	UnfollowDate time.Time
	LastAction   time.Time
}

const (
	_TABLE_FOLLOW = "follow"
)

func AlreadyFollow(userId int64) (bool, error) {
	stmtOut, err := database.Prepare("SELECT count(*) FROM " + _TABLE_FOLLOW + " WHERE userId = ? LIMIT 1")
	if err != nil {
		return true, err
	}

	defer stmtOut.Close()

	var size int

	err = stmtOut.QueryRow(userId).Scan(&size)
	if err != nil {
		return true, err
	}

	return size > 0, nil
}

func (follow Follow) Persist() error {
	var stmtIns *sql.Stmt
	var err error

	if follow.id == 0 {
		stmtIns, err = database.Prepare("INSERT INTO " + _TABLE_FOLLOW + "(userId, userName, status, followDate, unfollowDate, lastAction) VALUES( ?, ?, ?, ?, ? ,?)")
	} else {
		stmtIns, err = database.Prepare("UPDATE " + _TABLE_FOLLOW + " SET userId = ?, userName = ?, status = ?, followDate = ?, unfollowDate = ?, lastAction = ? WHERE id = ?")
	}

	if err != nil {
		return err
	}

	defer stmtIns.Close()

	if follow.id == 0 {
		_, err = stmtIns.Exec(follow.UserId, follow.UserName, follow.Status, follow.FollowDate, follow.UnfollowDate, time.Now())
	} else {
		_, err = stmtIns.Exec(follow.UserId, follow.UserName, follow.Status, follow.FollowDate, follow.UnfollowDate, follow.LastAction, follow.id)
	}

	return err
}

func GetNotUnfollowed(maxFollowDate time.Time, limit int) ([]Follow, error) {
	follows := make([]Follow, 0)

	stmtOut, err := database.Prepare("SELECT * FROM " + _TABLE_FOLLOW + " WHERE unfollowDate IS NULL AND followDate <= ? ORDER BY lastAction LIMIT ?")
	if err != nil {
		return follows, err
	}

	defer stmtOut.Close()

	rows, err := stmtOut.Query(maxFollowDate, limit)
	if err != nil {
		return follows, err
	}

	defer rows.Close()

	for rows.Next() {
		follow, err := mapFollow(rows)
		if err != nil {
			return follows, err
		}

		follows = append(follows, follow)
	}

	return follows, nil
}

func mapFollow(rows *sql.Rows) (Follow, error) {
	var id int
	var userId int64
	var userName string
	var status string
	var followDate time.Time
	var unfollowDate mysql.NullTime
	var lastAction time.Time

	err := rows.Scan(&id, &userId, &userName, &status, &followDate, &unfollowDate, &lastAction)
	if err != nil {
		return Follow{}, err
	}

	var unfollowTime time.Time
	if unfollowDate.Valid {
		unfollowTime = unfollowDate.Time
	}

	return Follow{id: id, UserId: userId, UserName: userName, Status: status, FollowDate: followDate, UnfollowDate: unfollowTime, LastAction: lastAction}, nil
}
<commit_msg>Fix zero value with unfollow date<commit_after>package db

import (
	"database/sql"
	"github.com/go-sql-driver/mysql"
	"time"
)

type Follow struct {
	id           int
	UserId       int64
	UserName     string
	Status       string
	FollowDate   time.Time
	UnfollowDate time.Time
	LastAction   time.Time
}

const (
	_TABLE_FOLLOW = "follow"
)

func AlreadyFollow(userId int64) (bool, error) {
	stmtOut, err := database.Prepare("SELECT count(*) FROM " + _TABLE_FOLLOW + " WHERE userId = ? LIMIT 1")
	if err != nil {
		return true, err
	}

	defer stmtOut.Close()

	var size int

	err = stmtOut.QueryRow(userId).Scan(&size)
	if err != nil {
		return true, err
	}

	return size > 0, nil
}

func (follow Follow) Persist() error {
	var stmtIns *sql.Stmt
	var err error

	if follow.id == 0 {
		stmtIns, err = database.Prepare("INSERT INTO " + _TABLE_FOLLOW + "(userId, userName, status, followDate, unfollowDate, lastAction) VALUES( ?, ?, ?, ?, ? ,?)")
	} else {
		stmtIns, err = database.Prepare("UPDATE " + _TABLE_FOLLOW + " SET userId = ?, userName = ?, status = ?, followDate = ?, unfollowDate = ?, lastAction = ? WHERE id = ?")
	}

	if err != nil {
		return err
	}

	defer stmtIns.Close()

	unfollowDate := mysql.NullTime{Time: follow.UnfollowDate, Valid: !follow.UnfollowDate.IsZero()}

	if follow.id == 0 {
		_, err = stmtIns.Exec(follow.UserId, follow.UserName, follow.Status, follow.FollowDate, unfollowDate, time.Now())
	} else {
		_, err = stmtIns.Exec(follow.UserId, follow.UserName, follow.Status, follow.FollowDate, unfollowDate, follow.LastAction, follow.id)
	}

	return err
}

func GetNotUnfollowed(maxFollowDate time.Time, limit int) ([]Follow, error) {
	follows := make([]Follow, 0)

	stmtOut, err := database.Prepare("SELECT * FROM " + _TABLE_FOLLOW + " WHERE unfollowDate IS NULL AND followDate <= ? ORDER BY lastAction LIMIT ?")
	if err != nil {
		return follows, err
	}

	defer stmtOut.Close()

	rows, err := stmtOut.Query(maxFollowDate, limit)
	if err != nil {
		return follows, err
	}

	defer rows.Close()

	for rows.Next() {
		follow, err := mapFollow(rows)
		if err != nil {
			return follows, err
		}

		follows = append(follows, follow)
	}

	return follows, nil
}

func mapFollow(rows *sql.Rows) (Follow, error) {
	var id int
	var userId int64
	var userName string
	var status string
	var followDate time.Time
	var unfollowDate mysql.NullTime
	var lastAction time.Time

	err := rows.Scan(&id, &userId, &userName, &status, &followDate, &unfollowDate, &lastAction)
	if err != nil {
		return Follow{}, err
	}

	var unfollowTime time.Time
	if unfollowDate.Valid {
		unfollowTime = unfollowDate.Time
	}

	return Follow{id: id, UserId: userId, UserName: userName, Status: status, FollowDate: followDate, UnfollowDate: unfollowTime, LastAction: lastAction}, nil
}
<|endoftext|>


<commit_before>package aws

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"testing"
)

func TestAccAWSPolicyAttachment_basic(t *testing.T) {
	var out iam.GetPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attachment", 3, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user"}, []string{"test-role"}, []string{"test-group"}, &out),
				),
			},
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfigUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attachment", 6, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user3", "test-user3"}, []string{"test-role2", "test-role3"}, []string{"test-group2", "test-group3"}, &out),
				),
			},
		},
	})
}
func testAccCheckAWSPolicyAttachmentDestroy(s *terraform.State) error {

	return nil
}

func testAccCheckAWSPolicyAttachmentExists(n string, c int, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy name is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).iamconn
		arn := rs.Primary.Attributes["policy_arn"]

		resp, err := conn.GetPolicy(&iam.GetPolicyInput{
			PolicyARN: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Policy (%s) not found", n)
		}
		if c != resp.Policy.AttachmentCount {
			return fmt.Errorf("Error: Policy (%s) has wrong number of entities attached on initial creation", n)
		}
		resp2, err := conn.ListEntitiesForPolicy(&iam.ListEntitiesForPolicyOutput{
			PolicyARN: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Failed to get entities for Policy (%s)", arn)
		}

		*out = *resp2
		return nil
	}
}
func testAccCheckAWSPolicyAttachmentAttributes(users []string, roles []string, groups []string, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		uc := len(u)
		rc := len(r)
		gc := len(g)

		for _, u := range users {
			for _, pu := range out.PolicyUsers {
				if u == *pu.UserName {
					uc--
				}
			}
		}
		for _, r := range roles {
			for _, pr := range out.PolicyRoles {
				if r == *pu.RoleName {
					rc--
				}
			}
		}
		for _, g := range users {
			for _, pg := range out.PolicyGroups {
				if g == *pu.GroupName {
					gc--
				}
			}
		}
		if uc != 0 || rc != 0 || gc != 0 {
			return fmt.Errorf("Error: Number of attached users, roles, or groups was incorrect:\n expected %d users and found %d\nexpected %d roles and found %d\nexpected %d groups and found %d", len(users), (len(users) - uc), len(roles), (len(roles) - rc), len(groups), (len(groups) - gc))
		}
	}
}

const testAccAWSPolicyAttachConfig = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_role" "role" {
    name = "test-role"
}
resource "aws_iam_group" "group" {
    name = "test-group"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.name}"]
    roles = ["${aws_iam_role.role.name}"]
    groups = ["${aws_iam_group.group.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyAttachConfigUpdate = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_user" "user2" {
    name = "test-user2"
}
resource "aws_iam_user" "user3" {
    name = "test-user3"
}
resource "aws_iam_role" "role" {
    name = "test-role"
}
resource "aws_iam_role" "role2" {
    name = "test-role2"
}
resource "aws_iam_role" "role3" {
    name = "test-role3"
}
resource "aws_iam_group" "group" {
    name = "test-group"
}
resource "aws_iam_group" "group2" {
    name = "test-group2"
}
resource "aws_iam_group" "group3" {
    name = "test-group3"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = [
        "${aws_iam_user.user2.name}",
        "${aws_iam_user.user3.name}"
    ]
    roles = [
        "${aws_iam_role.role2.name}",
        "${aws_iam_role.role3.name}"
    ]
    groups = [
        "${aws_iam_group.group2.name}",
        "${aws_iam_group.group3.name}"
    ]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`
<commit_msg>test works<commit_after>package aws

import (
	"fmt"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/iam"
	"github.com/hashicorp/terraform/helper/resource"
	"github.com/hashicorp/terraform/terraform"
	"testing"
)

func TestAccAWSPolicyAttachment_basic(t *testing.T) {
	var out iam.ListEntitiesForPolicyOutput

	resource.Test(t, resource.TestCase{
		PreCheck:     func() { testAccPreCheck(t) },
		Providers:    testAccProviders,
		CheckDestroy: testAccCheckAWSPolicyAttachmentDestroy,
		Steps: []resource.TestStep{
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfig,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attachment", 3, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user"}, []string{"test-role"}, []string{"test-group"}, &out),
				),
			},
			resource.TestStep{
				Config: testAccAWSPolicyAttachConfigUpdate,
				Check: resource.ComposeTestCheckFunc(
					testAccCheckAWSPolicyAttachmentExists("aws_iam_policy_attachment.test-attachment", 6, &out),
					testAccCheckAWSPolicyAttachmentAttributes([]string{"test-user3", "test-user3"}, []string{"test-role2", "test-role3"}, []string{"test-group2", "test-group3"}, &out),
				),
			},
		},
	})
}
func testAccCheckAWSPolicyAttachmentDestroy(s *terraform.State) error {

	return nil
}

func testAccCheckAWSPolicyAttachmentExists(n string, c int64, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		rs, ok := s.RootModule().Resources[n]
		if !ok {
			return fmt.Errorf("Not found: %s", n)
		}

		if rs.Primary.ID == "" {
			return fmt.Errorf("No policy name is set")
		}

		conn := testAccProvider.Meta().(*AWSClient).iamconn
		arn := rs.Primary.Attributes["policy_arn"]

		resp, err := conn.GetPolicy(&iam.GetPolicyInput{
			PolicyARN: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Policy (%s) not found", n)
		}
		if c != *resp.Policy.AttachmentCount {
			return fmt.Errorf("Error: Policy (%s) has wrong number of entities attached on initial creation", n)
		}
		resp2, err := conn.ListEntitiesForPolicy(&iam.ListEntitiesForPolicyInput{
			PolicyARN: aws.String(arn),
		})
		if err != nil {
			return fmt.Errorf("Error: Failed to get entities for Policy (%s)", arn)
		}

		*out = *resp2
		return nil
	}
}
func testAccCheckAWSPolicyAttachmentAttributes(users []string, roles []string, groups []string, out *iam.ListEntitiesForPolicyOutput) resource.TestCheckFunc {
	return func(s *terraform.State) error {
		uc := len(users)
		rc := len(roles)
		gc := len(groups)

		for _, u := range users {
			for _, pu := range out.PolicyUsers {
				if u == *pu.UserName {
					uc--
				}
			}
		}
		for _, r := range roles {
			for _, pr := range out.PolicyRoles {
				if r == *pr.RoleName {
					rc--
				}
			}
		}
		for _, g := range users {
			for _, pg := range out.PolicyGroups {
				if g == *pg.GroupName {
					gc--
				}
			}
		}
		if uc != 0 || rc != 0 || gc != 0 {
			return fmt.Errorf("Error: Number of attached users, roles, or groups was incorrect:\n expected %d users and found %d\nexpected %d roles and found %d\nexpected %d groups and found %d", len(users), (len(users) - uc), len(roles), (len(roles) - rc), len(groups), (len(groups) - gc))
		}
		return nil
	}
}

const testAccAWSPolicyAttachConfig = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_role" "role" {
    name = "test-role"
}
resource "aws_iam_group" "group" {
    name = "test-group"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = ["${aws_iam_user.user.name}"]
    roles = ["${aws_iam_role.role.name}"]
    groups = ["${aws_iam_group.group.name}"]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`

const testAccAWSPolicyAttachConfigUpdate = `
resource "aws_iam_user" "user" {
    name = "test-user"
}
resource "aws_iam_user" "user2" {
    name = "test-user2"
}
resource "aws_iam_user" "user3" {
    name = "test-user3"
}
resource "aws_iam_role" "role" {
    name = "test-role"
}
resource "aws_iam_role" "role2" {
    name = "test-role2"
}
resource "aws_iam_role" "role3" {
    name = "test-role3"
}
resource "aws_iam_group" "group" {
    name = "test-group"
}
resource "aws_iam_group" "group2" {
    name = "test-group2"
}
resource "aws_iam_group" "group3" {
    name = "test-group3"
}

resource "aws_iam_policy" "policy" {
    name = "test-policy"
    description = "A test policy"
    policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

resource "aws_iam_policy_attachment" "test-attach" {
    name = "test-attachment"
    users = [
        "${aws_iam_user.user2.name}",
        "${aws_iam_user.user3.name}"
    ]
    roles = [
        "${aws_iam_role.role2.name}",
        "${aws_iam_role.role3.name}"
    ]
    groups = [
        "${aws_iam_group.group2.name}",
        "${aws_iam_group.group3.name}"
    ]
    policy_arn = "${aws_iam_policy.policy.arn}"
}
`
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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 priorities

import (
	"context"
	"sync"
	"sync/atomic"

	"k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/util/workqueue"
	"k8s.io/kubernetes/pkg/scheduler/algorithm"
	"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
	priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util"
	schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
	schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"

	"k8s.io/klog"
)

// InterPodAffinity contains information to calculate inter pod affinity.
type InterPodAffinity struct {
	info                  predicates.NodeInfo
	nodeLister            algorithm.NodeLister
	podLister             algorithm.PodLister
	hardPodAffinityWeight int32
}

// NewInterPodAffinityPriority creates an InterPodAffinity.
func NewInterPodAffinityPriority(
	info predicates.NodeInfo,
	nodeLister algorithm.NodeLister,
	podLister algorithm.PodLister,
	hardPodAffinityWeight int32) PriorityFunction {
	interPodAffinity := &InterPodAffinity{
		info:                  info,
		nodeLister:            nodeLister,
		podLister:             podLister,
		hardPodAffinityWeight: hardPodAffinityWeight,
	}
	return interPodAffinity.CalculateInterPodAffinityPriority
}

type podAffinityPriorityMap struct {
	sync.Mutex

	// nodes contain all nodes that should be considered
	nodes []*v1.Node
	// counts store the mapping from node name to so-far computed score of
	// the node.
	counts map[string]*int64
	// The first error that we faced.
	firstError error
}

func newPodAffinityPriorityMap(nodes []*v1.Node) *podAffinityPriorityMap {
	return &podAffinityPriorityMap{
		nodes:  nodes,
		counts: make(map[string]*int64, len(nodes)),
	}
}

func (p *podAffinityPriorityMap) setError(err error) {
	p.Lock()
	defer p.Unlock()
	if p.firstError == nil {
		p.firstError = err
	}
}

func (p *podAffinityPriorityMap) processTerm(term *v1.PodAffinityTerm, podDefiningAffinityTerm, podToCheck *v1.Pod, fixedNode *v1.Node, weight int64) {
	namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(podDefiningAffinityTerm, term)
	selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector)
	if err != nil {
		p.setError(err)
		return
	}
	match := priorityutil.PodMatchesTermsNamespaceAndSelector(podToCheck, namespaces, selector)
	if match {
		for _, node := range p.nodes {
			if priorityutil.NodesHaveSameTopologyKey(node, fixedNode, term.TopologyKey) {
				atomic.AddInt64(p.counts[node.Name], weight)
			}
		}
	}
}

func (p *podAffinityPriorityMap) processTerms(terms []v1.WeightedPodAffinityTerm, podDefiningAffinityTerm, podToCheck *v1.Pod, fixedNode *v1.Node, multiplier int) {
	for i := range terms {
		term := &terms[i]
		p.processTerm(&term.PodAffinityTerm, podDefiningAffinityTerm, podToCheck, fixedNode, int64(term.Weight*int32(multiplier)))
	}
}

// CalculateInterPodAffinityPriority compute a sum by iterating through the elements of weightedPodAffinityTerm and adding
// "weight" to the sum if the corresponding PodAffinityTerm is satisfied for
// that node; the node(s) with the highest sum are the most preferred.
// Symmetry need to be considered for preferredDuringSchedulingIgnoredDuringExecution from podAffinity & podAntiAffinity,
// symmetry need to be considered for hard requirements from podAffinity
func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) {
	affinity := pod.Spec.Affinity
	hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil
	hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil

	// priorityMap stores the mapping from node name to so-far computed score of
	// the node.
	pm := newPodAffinityPriorityMap(nodes)
	allNodeNames := make([]string, 0, len(nodeNameToInfo))
	for name := range nodeNameToInfo {
		allNodeNames = append(allNodeNames, name)
		pm.counts[name] = new(int64)
	}

	// convert the topology key based weights to the node name based weights
	var maxCount, minCount int64

	processPod := func(existingPod *v1.Pod) error {
		existingPodNode, err := ipa.info.GetNodeInfo(existingPod.Spec.NodeName)
		if err != nil {
			if apierrors.IsNotFound(err) {
				klog.Errorf("Node not found, %v", existingPod.Spec.NodeName)
				return nil
			}
			return err
		}
		existingPodAffinity := existingPod.Spec.Affinity
		existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil
		existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil

		if hasAffinityConstraints {
			// For every soft pod affinity term of <pod>, if <existingPod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPods>`s node by the term`s weight.
			terms := affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, pod, existingPod, existingPodNode, 1)
		}
		if hasAntiAffinityConstraints {
			// For every soft pod anti-affinity term of <pod>, if <existingPod> matches the term,
			// decrement <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>`s node by the term`s weight.
			terms := affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, pod, existingPod, existingPodNode, -1)
		}

		if existingHasAffinityConstraints {
			// For every hard pod affinity term of <existingPod>, if <pod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the constant <ipa.hardPodAffinityWeight>
			if ipa.hardPodAffinityWeight > 0 {
				terms := existingPodAffinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution
				// TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution.
				//if len(existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution) != 0 {
				//	terms = append(terms, existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution...)
				//}
				for _, term := range terms {
					pm.processTerm(&term, existingPod, pod, existingPodNode, int64(ipa.hardPodAffinityWeight))
				}
			}
			// For every soft pod affinity term of <existingPod>, if <pod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the term's weight.
			terms := existingPodAffinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, existingPod, pod, existingPodNode, 1)
		}
		if existingHasAntiAffinityConstraints {
			// For every soft pod anti-affinity term of <existingPod>, if <pod> matches the term,
			// decrement <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the term's weight.
			terms := existingPodAffinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, existingPod, pod, existingPodNode, -1)
		}
		return nil
	}
	processNode := func(i int) {
		nodeInfo := nodeNameToInfo[allNodeNames[i]]
		if nodeInfo.Node() != nil {
			if hasAffinityConstraints || hasAntiAffinityConstraints {
				// We need to process all the nodes.
				for _, existingPod := range nodeInfo.Pods() {
					if err := processPod(existingPod); err != nil {
						pm.setError(err)
					}
				}
			} else {
				// The pod doesn't have any constraints - we need to check only existing
				// ones that have some.
				for _, existingPod := range nodeInfo.PodsWithAffinity() {
					if err := processPod(existingPod); err != nil {
						pm.setError(err)
					}
				}
			}
		}
	}
	workqueue.ParallelizeUntil(context.TODO(), 16, len(allNodeNames), processNode)
	if pm.firstError != nil {
		return nil, pm.firstError
	}

	for _, node := range nodes {
		if *pm.counts[node.Name] > maxCount {
			maxCount = *pm.counts[node.Name]
		}
		if *pm.counts[node.Name] < minCount {
			minCount = *pm.counts[node.Name]
		}
	}

	// calculate final priority score for each node
	result := make(schedulerapi.HostPriorityList, 0, len(nodes))
	for _, node := range nodes {
		fScore := float64(0)
		if (maxCount - minCount) > 0 {
			fScore = float64(schedulerapi.MaxPriority) * (float64(*pm.counts[node.Name]-minCount) / float64(maxCount-minCount))
		}
		result = append(result, schedulerapi.HostPriority{Host: node.Name, Score: int(fScore)})
		if klog.V(10) {
			klog.Infof("%v -> %v: InterPodAffinityPriority, Score: (%d)", pod.Name, node.Name, int(fScore))
		}
	}
	return result, nil
}
<commit_msg>lazy/dynamic initilization on the int64 pointers of inter-podaffinity priority<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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 priorities

import (
	"context"
	"sync"
	"sync/atomic"

	"k8s.io/api/core/v1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/util/workqueue"
	"k8s.io/kubernetes/pkg/scheduler/algorithm"
	"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
	priorityutil "k8s.io/kubernetes/pkg/scheduler/algorithm/priorities/util"
	schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
	schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"

	"k8s.io/klog"
)

// InterPodAffinity contains information to calculate inter pod affinity.
type InterPodAffinity struct {
	info                  predicates.NodeInfo
	nodeLister            algorithm.NodeLister
	podLister             algorithm.PodLister
	hardPodAffinityWeight int32
}

// NewInterPodAffinityPriority creates an InterPodAffinity.
func NewInterPodAffinityPriority(
	info predicates.NodeInfo,
	nodeLister algorithm.NodeLister,
	podLister algorithm.PodLister,
	hardPodAffinityWeight int32) PriorityFunction {
	interPodAffinity := &InterPodAffinity{
		info:                  info,
		nodeLister:            nodeLister,
		podLister:             podLister,
		hardPodAffinityWeight: hardPodAffinityWeight,
	}
	return interPodAffinity.CalculateInterPodAffinityPriority
}

type podAffinityPriorityMap struct {
	sync.Mutex

	// nodes contain all nodes that should be considered
	nodes []*v1.Node
	// counts store the mapping from node name to so-far computed score of
	// the node.
	counts map[string]*int64
	// The first error that we faced.
	firstError error
}

func newPodAffinityPriorityMap(nodes []*v1.Node) *podAffinityPriorityMap {
	return &podAffinityPriorityMap{
		nodes:  nodes,
		counts: make(map[string]*int64, len(nodes)),
	}
}

func (p *podAffinityPriorityMap) setError(err error) {
	p.Lock()
	defer p.Unlock()
	if p.firstError == nil {
		p.firstError = err
	}
}

func (p *podAffinityPriorityMap) processTerm(term *v1.PodAffinityTerm, podDefiningAffinityTerm, podToCheck *v1.Pod, fixedNode *v1.Node, weight int64) {
	namespaces := priorityutil.GetNamespacesFromPodAffinityTerm(podDefiningAffinityTerm, term)
	selector, err := metav1.LabelSelectorAsSelector(term.LabelSelector)
	if err != nil {
		p.setError(err)
		return
	}
	match := priorityutil.PodMatchesTermsNamespaceAndSelector(podToCheck, namespaces, selector)
	if match {
		for _, node := range p.nodes {
			if priorityutil.NodesHaveSameTopologyKey(node, fixedNode, term.TopologyKey) {
				atomic.AddInt64(p.counts[node.Name], weight)
			}
		}
	}
}

func (p *podAffinityPriorityMap) processTerms(terms []v1.WeightedPodAffinityTerm, podDefiningAffinityTerm, podToCheck *v1.Pod, fixedNode *v1.Node, multiplier int) {
	for i := range terms {
		term := &terms[i]
		p.processTerm(&term.PodAffinityTerm, podDefiningAffinityTerm, podToCheck, fixedNode, int64(term.Weight*int32(multiplier)))
	}
}

// CalculateInterPodAffinityPriority compute a sum by iterating through the elements of weightedPodAffinityTerm and adding
// "weight" to the sum if the corresponding PodAffinityTerm is satisfied for
// that node; the node(s) with the highest sum are the most preferred.
// Symmetry need to be considered for preferredDuringSchedulingIgnoredDuringExecution from podAffinity & podAntiAffinity,
// symmetry need to be considered for hard requirements from podAffinity
func (ipa *InterPodAffinity) CalculateInterPodAffinityPriority(pod *v1.Pod, nodeNameToInfo map[string]*schedulernodeinfo.NodeInfo, nodes []*v1.Node) (schedulerapi.HostPriorityList, error) {
	affinity := pod.Spec.Affinity
	hasAffinityConstraints := affinity != nil && affinity.PodAffinity != nil
	hasAntiAffinityConstraints := affinity != nil && affinity.PodAntiAffinity != nil

	// priorityMap stores the mapping from node name to so-far computed score of
	// the node.
	pm := newPodAffinityPriorityMap(nodes)
	allNodeNames := make([]string, 0, len(nodeNameToInfo))
	lazyInit := hasAffinityConstraints || hasAntiAffinityConstraints
	for name := range nodeNameToInfo {
		allNodeNames = append(allNodeNames, name)
		// if pod has affinity defined, or target node has affinityPods
		if lazyInit || len(nodeNameToInfo[name].PodsWithAffinity()) != 0 {
			pm.counts[name] = new(int64)
		}
	}

	// convert the topology key based weights to the node name based weights
	var maxCount, minCount int64

	processPod := func(existingPod *v1.Pod) error {
		existingPodNode, err := ipa.info.GetNodeInfo(existingPod.Spec.NodeName)
		if err != nil {
			if apierrors.IsNotFound(err) {
				klog.Errorf("Node not found, %v", existingPod.Spec.NodeName)
				return nil
			}
			return err
		}
		existingPodAffinity := existingPod.Spec.Affinity
		existingHasAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAffinity != nil
		existingHasAntiAffinityConstraints := existingPodAffinity != nil && existingPodAffinity.PodAntiAffinity != nil

		if hasAffinityConstraints {
			// For every soft pod affinity term of <pod>, if <existingPod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPods>`s node by the term`s weight.
			terms := affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, pod, existingPod, existingPodNode, 1)
		}
		if hasAntiAffinityConstraints {
			// For every soft pod anti-affinity term of <pod>, if <existingPod> matches the term,
			// decrement <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>`s node by the term`s weight.
			terms := affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, pod, existingPod, existingPodNode, -1)
		}

		if existingHasAffinityConstraints {
			// For every hard pod affinity term of <existingPod>, if <pod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the constant <ipa.hardPodAffinityWeight>
			if ipa.hardPodAffinityWeight > 0 {
				terms := existingPodAffinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution
				// TODO: Uncomment this block when implement RequiredDuringSchedulingRequiredDuringExecution.
				//if len(existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution) != 0 {
				//	terms = append(terms, existingPodAffinity.PodAffinity.RequiredDuringSchedulingRequiredDuringExecution...)
				//}
				for _, term := range terms {
					pm.processTerm(&term, existingPod, pod, existingPodNode, int64(ipa.hardPodAffinityWeight))
				}
			}
			// For every soft pod affinity term of <existingPod>, if <pod> matches the term,
			// increment <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the term's weight.
			terms := existingPodAffinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, existingPod, pod, existingPodNode, 1)
		}
		if existingHasAntiAffinityConstraints {
			// For every soft pod anti-affinity term of <existingPod>, if <pod> matches the term,
			// decrement <pm.counts> for every node in the cluster with the same <term.TopologyKey>
			// value as that of <existingPod>'s node by the term's weight.
			terms := existingPodAffinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution
			pm.processTerms(terms, existingPod, pod, existingPodNode, -1)
		}
		return nil
	}
	processNode := func(i int) {
		nodeInfo := nodeNameToInfo[allNodeNames[i]]
		if nodeInfo.Node() != nil {
			if hasAffinityConstraints || hasAntiAffinityConstraints {
				// We need to process all the pods.
				for _, existingPod := range nodeInfo.Pods() {
					if err := processPod(existingPod); err != nil {
						pm.setError(err)
					}
				}
			} else {
				// The pod doesn't have any constraints - we need to check only existing
				// ones that have some.
				for _, existingPod := range nodeInfo.PodsWithAffinity() {
					if err := processPod(existingPod); err != nil {
						pm.setError(err)
					}
				}
			}
		}
	}
	workqueue.ParallelizeUntil(context.TODO(), 16, len(allNodeNames), processNode)
	if pm.firstError != nil {
		return nil, pm.firstError
	}

	for _, node := range nodes {
		if pm.counts[node.Name] == nil {
			continue
		}
		if *pm.counts[node.Name] > maxCount {
			maxCount = *pm.counts[node.Name]
		}
		if *pm.counts[node.Name] < minCount {
			minCount = *pm.counts[node.Name]
		}
	}

	// calculate final priority score for each node
	result := make(schedulerapi.HostPriorityList, 0, len(nodes))
	maxMinDiff := maxCount - minCount
	for _, node := range nodes {
		fScore := float64(0)
		if maxMinDiff > 0 && pm.counts[node.Name] != nil {
			fScore = float64(schedulerapi.MaxPriority) * (float64(*pm.counts[node.Name]-minCount) / float64(maxCount-minCount))
		}
		result = append(result, schedulerapi.HostPriority{Host: node.Name, Score: int(fScore)})
		if klog.V(10) {
			klog.Infof("%v -> %v: InterPodAffinityPriority, Score: (%d)", pod.Name, node.Name, int(fScore))
		}
	}
	return result, nil
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"math"
)

type myCipher struct {
	plainText, cipherText, currentText string
	cipherTextArr                      []string
	matrix                             [][]string
}

func (c *myCipher) encrypt(key string) {

}

func (c *myCipher) decrypt(index int) {
	fmt.Println(c.cipherTextArr)
}

func (c *myCipher) showMatrix(s string) {

	length, col, row := getMatrixDimensions(s)
	c.matrix = make([][]string, row)
	c.cipherTextArr = make([]string, col)
	for x := range c.matrix {
		c.matrix[x] = make([]string, col)
	}
	l := 0
	for i := 0; i < row; i++ {
		for j := 0; j < col; j++ {
			if length > l {
				c.matrix[i][j] = string(s[l])
			} else {
				c.matrix[i][j] = "\\"
			}
			fmt.Print(c.matrix[i][j], " ")
			l++
		}
		fmt.Println()
	}
}

func getMatrixDimensions(s string) (int, int, int) {
	length := len(s)
	col := int(math.Ceil(math.Sqrt(float64(length))))
	row := int(math.Ceil(float64(length) / float64(col)))

	return length, col, row
}

func options() {
	fmt.Println("Please select an action to perform")
	fmt.Println("1. Provide text to encrypt")
	fmt.Println("2. Select text to decrypt")
	fmt.Println("3. View plain text matrix")
	fmt.Println("4. View cipher text matrix")
}

func main() {
	test := new(myCipher)
	var key string
	fmt.Println("Enter text to encrypt: ")
	fmt.Scanln(&test.plainText)
	test.showMatrix(test.plainText)
	fmt.Println("Enter encryption key: ")

	fmt.Scanln(&key)

	test.decrypt(0)

}
<commit_msg>Added new functionality<commit_after>package main

import (
	"fmt"
	"hash/fnv"
	"math"
	"math/rand"
)

type dimensions struct {
	length, col, row int
}
type myCipher struct {
	plainText, cipherText, currentText string
	cipherTextArr                      []string
	cipherTextIdx                      []int
	plainTextMatrix                    [][]string
	cipherTextMatrix                   [][]string
	d                                  dimensions
}

func (c *myCipher) encrypt(key string) {
	c.hashKey(key)
	for i := 0; i < c.d.row; i++ {
		for j := 0; j < len(c.cipherTextIdx); j++ {
			c.cipherTextMatrix[i][j] = c.plainTextMatrix[i][c.cipherTextIdx[j]]
			c.cipherText += c.cipherTextMatrix[i][j]
		}
		c.cipherText += " "
	}
}

func (c *myCipher) decrypt(key string) {
	c.hashKey(key)
	for i := 0; i < len(c.cipherTextIdx); i++ {
		for j := 0; j < c.d.row; j++ {
			c.cipherTextMatrix[i][j] = c.plainTextMatrix[i][c.cipherTextIdx[j]]
			c.cipherText += c.plainTextMatrix[i][j]
		}
	}
}

func (c *myCipher) hashKey(key string) {
	k := []byte(key)
	hash := fnv.New64a()
	hash.Write(k)
	rand.Seed(int64(hash.Sum64()))
	c.cipherTextIdx = rand.Perm(c.d.col)
}

func (c *myCipher) createMatrix(s string) {
	c.init(s)
	l := 0
	for i := 0; i < c.d.row; i++ {
		for j := 0; j < c.d.col; j++ {
			if c.d.length > l {
				c.plainTextMatrix[i][j] = string(s[l])
			} else {
				c.plainTextMatrix[i][j] = "\\"
			}
			l++
		}
	}
	c.showMatrix()
}

func (c *myCipher) showMatrix() {
	fmt.Println()
	for i := 0; i < c.d.row; i++ {
		for j := 0; j < c.d.col; j++ {
			fmt.Print(c.plainTextMatrix[i][j], " ")
		}
		fmt.Println()
	}
	fmt.Println()
}

func (c *myCipher) init(s string) {
	c.d.length = len(s)
	c.d.col = int(math.Ceil(math.Sqrt(float64(c.d.length))))
	c.d.row = int(math.Ceil(float64(c.d.length) / float64(c.d.col)))
	c.plainTextMatrix = make([][]string, c.d.row)
	c.cipherTextMatrix = make([][]string, c.d.row)
	c.cipherTextArr = make([]string, c.d.col)
	c.cipherTextIdx = make([]int, c.d.col)

	for x := range c.plainTextMatrix {
		c.plainTextMatrix[x] = make([]string, c.d.col)
		c.cipherTextMatrix[x] = make([]string, c.d.col)
	}
}

func (c *myCipher) showPlainText() {
	fmt.Println("Plain Text: ", c.plainText)
	fmt.Println()
}

func (c *myCipher) showCipherText() {
	fmt.Println("Cipher Text: ", c.cipherText)
	fmt.Println()
}

func options() {
	fmt.Println()
	fmt.Println("Please select an action to perform")
	fmt.Println("1. Provide text to encrypt")
	fmt.Println("2. Select text to decrypt")
	fmt.Println("3. View plain text matrix")
	fmt.Println("4. View cipher text matrix")
	fmt.Println("5. View options")
	fmt.Println("6. Exit")
	fmt.Println()
}

func main() {
	test := new(myCipher)
	var key string
	fmt.Println("Select action: ")

	var userInput int
	for {
		options()

		fmt.Scanf("%d", &userInput)

		if userInput == 1 {
			fmt.Println("Enter text to encrypt: ")
			fmt.Scanln(&test.plainText)
			test.createMatrix(test.plainText)
			fmt.Println("Enter encryption key: ")
			fmt.Scanln(&key)
			fmt.Println()
			test.encrypt(key)
			test.showCipherText()
			continue
		} else if userInput == 2 {
			fmt.Println("Enter text to decrypt: ")
			fmt.Scanln(&test.cipherText)
			test.createMatrix(test.cipherText)
			fmt.Println("Enter key: ")
			fmt.Scanln(&key)
			fmt.Println()
			test.encrypt(key)
			test.showCipherText()
			continue
		} else if userInput == 3 {

		} else if userInput == 4 {

		} else if userInput == 5 {

		} else if userInput == 6 {
			break
		} else {
			options()
			continue
		}
	}

}
<|endoftext|>


<commit_before>// Copyright 2020 Asim Aslam
//
// 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
//
//     https://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.
//
// Original source: github.com/micro/go-plugins/v3/metrics/prometheus/reporter.go

package prometheus

import (
	"net/http"
	"strings"

	log "github.com/micro/micro/v3/service/logger"
	"github.com/micro/micro/v3/service/metrics"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	// quantileThresholds maps quantiles / percentiles to error thresholds (required by the Prometheus client).
	// Must be from our pre-defined set [0.0, 0.5, 0.75, 0.90, 0.95, 0.98, 0.99, 1]:
	quantileThresholds = map[float64]float64{0.0: 0, 0.5: 0.05, 0.75: 0.04, 0.90: 0.03, 0.95: 0.02, 0.98: 0.001, 1: 0}
)

// Reporter is an implementation of metrics.Reporter:
type Reporter struct {
	options            metrics.Options
	prometheusRegistry *prometheus.Registry
	metrics            metricFamily
}

// New returns a configured prometheus reporter:
func New(opts ...metrics.Option) (*Reporter, error) {
	options := metrics.NewOptions(opts...)

	// Make a prometheus registry (this keeps track of any metrics we generate):
	prometheusRegistry := prometheus.NewRegistry()
	prometheusRegistry.Register(prometheus.NewGoCollector())
	prometheusRegistry.Register(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{Namespace: "goruntime"}))

	// Make a new Reporter:
	newReporter := &Reporter{
		options:            options,
		prometheusRegistry: prometheusRegistry,
	}

	// Add metrics families for each type:
	newReporter.metrics = newReporter.newMetricFamily()

	// Handle the metrics endpoint with prometheus:
	log.Infof("Metrics/Prometheus [http] Listening on %s%s", options.Address, options.Path)
	http.Handle(options.Path, promhttp.HandlerFor(prometheusRegistry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))
	go http.ListenAndServe(options.Address, nil)

	return newReporter, nil
}

// convertTags turns Tags into prometheus labels:
func (r *Reporter) convertTags(tags metrics.Tags) prometheus.Labels {
	labels := prometheus.Labels{}
	for key, value := range tags {
		labels[key] = r.stripUnsupportedCharacters(value)
	}
	return labels
}

// listTagKeys returns a list of tag keys (we need to provide this to the Prometheus client):
func (r *Reporter) listTagKeys(tags metrics.Tags) (labelKeys []string) {
	for key := range tags {
		labelKeys = append(labelKeys, key)
	}
	return
}

// stripUnsupportedCharacters cleans up a metrics key or value:
func (r *Reporter) stripUnsupportedCharacters(metricName string) string {
	valueWithoutDots := strings.Replace(metricName, ".", "_", -1)
	valueWithoutCommas := strings.Replace(valueWithoutDots, ",", "_", -1)
	valueWithoutSpaces := strings.Replace(valueWithoutCommas, " ", "", -1)
	return valueWithoutSpaces
}
<commit_msg>fix(prometheus): add 0.99 to pre-defined quantiles (#1760)<commit_after>// Copyright 2020 Asim Aslam
//
// 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
//
//     https://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.
//
// Original source: github.com/micro/go-plugins/v3/metrics/prometheus/reporter.go

package prometheus

import (
	"net/http"
	"strings"

	log "github.com/micro/micro/v3/service/logger"
	"github.com/micro/micro/v3/service/metrics"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

var (
	// quantileThresholds maps quantiles / percentiles to error thresholds (required by the Prometheus client).
	// Must be from our pre-defined set [0.0, 0.5, 0.75, 0.90, 0.95, 0.98, 0.99, 1]:
	quantileThresholds = map[float64]float64{0.0: 0, 0.5: 0.05, 0.75: 0.04, 0.90: 0.03, 0.95: 0.02, 0.98: 0.001, 0.99: 0.001, 1: 0}
)

// Reporter is an implementation of metrics.Reporter:
type Reporter struct {
	options            metrics.Options
	prometheusRegistry *prometheus.Registry
	metrics            metricFamily
}

// New returns a configured prometheus reporter:
func New(opts ...metrics.Option) (*Reporter, error) {
	options := metrics.NewOptions(opts...)

	// Make a prometheus registry (this keeps track of any metrics we generate):
	prometheusRegistry := prometheus.NewRegistry()
	prometheusRegistry.Register(prometheus.NewGoCollector())
	prometheusRegistry.Register(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{Namespace: "goruntime"}))

	// Make a new Reporter:
	newReporter := &Reporter{
		options:            options,
		prometheusRegistry: prometheusRegistry,
	}

	// Add metrics families for each type:
	newReporter.metrics = newReporter.newMetricFamily()

	// Handle the metrics endpoint with prometheus:
	log.Infof("Metrics/Prometheus [http] Listening on %s%s", options.Address, options.Path)
	http.Handle(options.Path, promhttp.HandlerFor(prometheusRegistry, promhttp.HandlerOpts{ErrorHandling: promhttp.ContinueOnError}))
	go http.ListenAndServe(options.Address, nil)

	return newReporter, nil
}

// convertTags turns Tags into prometheus labels:
func (r *Reporter) convertTags(tags metrics.Tags) prometheus.Labels {
	labels := prometheus.Labels{}
	for key, value := range tags {
		labels[key] = r.stripUnsupportedCharacters(value)
	}
	return labels
}

// listTagKeys returns a list of tag keys (we need to provide this to the Prometheus client):
func (r *Reporter) listTagKeys(tags metrics.Tags) (labelKeys []string) {
	for key := range tags {
		labelKeys = append(labelKeys, key)
	}
	return
}

// stripUnsupportedCharacters cleans up a metrics key or value:
func (r *Reporter) stripUnsupportedCharacters(metricName string) string {
	valueWithoutDots := strings.Replace(metricName, ".", "_", -1)
	valueWithoutCommas := strings.Replace(valueWithoutDots, ",", "_", -1)
	valueWithoutSpaces := strings.Replace(valueWithoutCommas, " ", "", -1)
	return valueWithoutSpaces
}
<|endoftext|>