text:
package bosh_test

import (
	"errors"
	"fmt"
	"io/ioutil"

	"github.com/cloudfoundry/bosh-bootloader/bosh"
	"github.com/cloudfoundry/bosh-bootloader/fakes"
	"github.com/cloudfoundry/bosh-bootloader/storage"
	"github.com/cloudfoundry/bosh-bootloader/terraform"

	"github.com/pivotal-cf-experimental/gomegamatchers"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Manager", func() {
	var (
		boshExecutor *fakes.BOSHExecutor
		logger       *fakes.Logger
		socks5Proxy  *fakes.Socks5Proxy
		stateStore   *fakes.StateStore
		sshKeyGetter *fakes.SSHKeyGetter

		boshManager      *bosh.Manager
		terraformOutputs terraform.Outputs
		boshVars         string

		osUnsetenvKey string
		osSetenvKey   string
		osSetenvValue string
	)

	BeforeEach(func() {
		boshExecutor = &fakes.BOSHExecutor{}
		logger = &fakes.Logger{}
		socks5Proxy = &fakes.Socks5Proxy{}
		sshKeyGetter = &fakes.SSHKeyGetter{}
		sshKeyGetter.GetCall.Returns.PrivateKey = "some-jumpbox-private-key"

		stateStore = &fakes.StateStore{}
		stateStore.GetVarsDirCall.Returns.Directory = "some-bbl-vars-dir"
		stateStore.GetStateDirCall.Returns.Directory = "some-state-dir"
		stateStore.GetDirectorDeploymentDirCall.Returns.Directory = "some-director-deployment-dir"
		stateStore.GetJumpboxDeploymentDirCall.Returns.Directory = "some-jumpbox-deployment-dir"

		boshManager = bosh.NewManager(boshExecutor, logger, socks5Proxy, stateStore, sshKeyGetter)

		boshVars = `admin_password: some-admin-password
director_ssl:
  ca: some-ca
  certificate: some-certificate
  private_key: some-private-key
`

		bosh.SetOSSetenv(func(key, value string) error {
			osSetenvKey = key
			osSetenvValue = value
			return nil
		})
		bosh.SetOSUnsetenv(func(key string) error {
			osUnsetenvKey = key
			return nil
		})
	})

	AfterEach(func() {
		bosh.ResetOSSetenv()
	})

	Describe("Director set-up", func() {
		var state storage.State
		BeforeEach(func() {
			state = storage.State{
				IAAS:  "gcp",
				EnvID: "some-env-id",
				GCP: storage.GCP{
					Zone:              "some-zone",
					ProjectID:         "some-project-id",
					ServiceAccountKey: "some-credential-json",
				},
				BOSH: storage.BOSH{
					State: map[string]interface{}{
						"some-key": "some-value",
					},
					UserOpsFile: "some-ops-file",
				},
			}

			boshExecutor.CreateEnvCall.Returns.Variables = boshVars
		})

		Describe("InitializeDirector", func() {
			It("Calls DirectorCreateEnvArgs", func() {
				err := boshManager.InitializeDirector(state)
				Expect(err).NotTo(HaveOccurred())
				Expect(boshExecutor.DirectorCreateEnvArgsCall.Receives.InterpolateInput.VarsDir).To(Equal("some-bbl-vars-dir"))
				Expect(boshExecutor.DirectorCreateEnvArgsCall.Receives.InterpolateInput.StateDir).To(Equal("some-state-dir"))
				Expect(boshExecutor.DirectorCreateEnvArgsCall.Receives.InterpolateInput.DeploymentDir).To(Equal("some-director-deployment-dir"))
				Expect(boshExecutor.JumpboxCreateEnvArgsCall.CallCount).To(Equal(0))

				Expect(boshExecutor.CreateEnvCall.CallCount).To(Equal(0))
			})

			Context("when create env args fails", func() {
				BeforeEach(func() {
					boshExecutor.DirectorCreateEnvArgsCall.Returns.Error = errors.New("failed to interpolate")
				})

				It("returns an error", func() {
					err := boshManager.InitializeDirector(storage.State{})
					Expect(err).To(MatchError("failed to interpolate"))
				})
			})

			Context("when get vars dir fails", func() {
				It("returns an error", func() {
					stateStore.GetVarsDirCall.Returns.Error = errors.New("pineapple")

					err := boshManager.InitializeDirector(storage.State{})
					Expect(err).To(MatchError("Get vars dir: pineapple"))
				})
			})

			Context("when get deployment dir fails", func() {
				It("returns an error", func() {
					stateStore.GetDirectorDeploymentDirCall.Returns.Error = errors.New("pineapple")

					err := boshManager.InitializeDirector(storage.State{})
					Expect(err).To(MatchError("Get deployment dir: pineapple"))
				})
			})
		})

		Describe("CreateDirector", func() {
			BeforeEach(func() {
				terraformOutputs = terraform.Outputs{Map: map[string]interface{}{
					"internal_cidr":          "10.2.0.0/24",
					"network_name":           "some-network",
					"subnetwork_name":        "some-subnetwork",
					"bosh_director_tag_name": "some-director-tag",
					"external_ip":            "some-external-ip",
					"some-key":               "some-value",
				}}
			})

			It("generates a bosh manifest", func() {
				stateWithDirector, err := boshManager.CreateDirector(state, terraformOutputs)
				Expect(err).NotTo(HaveOccurred())

				Expect(logger.StepCall.Messages).To(gomegamatchers.ContainSequence([]string{"creating bosh director", "created bosh director"}))

				Expect(boshExecutor.CreateEnvCall.Receives.Input.DeploymentVars).To(MatchYAML(`---
internal_cidr: 10.2.0.0/24
internal_gw: 10.2.0.1
internal_ip: 10.2.0.6
director_name: bosh-some-env-id
zone: some-zone
network: some-network
subnetwork: some-subnetwork
tags:
- some-director-tag
project_id: some-project-id
gcp_credentials_json: some-credential-json
bosh_director_tag_name: some-director-tag
network_name: some-network
subnetwork_name: some-subnetwork
some-key: some-value
`))
				Expect(boshExecutor.CreateEnvCall.CallCount).To(Equal(1))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.Deployment).To(Equal("director"))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.VarsDir).To(Equal("some-bbl-vars-dir"))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.StateDir).To(Equal("some-state-dir"))

				Expect(socks5Proxy.StartCall.CallCount).To(Equal(0))

				Expect(stateWithDirector.BOSH).To(Equal(storage.BOSH{
					DirectorName:           "bosh-some-env-id",
					DirectorAddress:        "https://10.2.0.6:25555",
					DirectorUsername:       "admin",
					DirectorPassword:       "some-admin-password",
					DirectorSSLCA:          "some-ca",
					DirectorSSLCertificate: "some-certificate",
					DirectorSSLPrivateKey:  "some-private-key",
					UserOpsFile:            "some-ops-file",
					State:                  nil,
				}))
			})

			Context("when an error occurs", func() {
				Context("when get vars dir fails", func() {
					It("returns an error", func() {
						stateStore.GetVarsDirCall.Returns.Error = errors.New("pineapple")

						_, err := boshManager.CreateDirector(storage.State{}, terraformOutputs)
						Expect(err).To(MatchError("Get vars dir: pineapple"))
					})
				})

				Context("when the executor's create env call fails with non create env error", func() {
					BeforeEach(func() {
						boshExecutor.CreateEnvCall.Returns.Error = errors.New("lychee")
					})

					It("returns an error", func() {
						_, err := boshManager.CreateDirector(storage.State{}, terraformOutputs)
						Expect(err).To(MatchError("Create director env: lychee"))
					})
				})
			})
		})
	})

	Describe("Jumpbox set-up", func() {
		var (
			deploymentVars string
			createEnvArgs  []string
			state          storage.State
		)

		BeforeEach(func() {
			terraformOutputs = terraform.Outputs{Map: map[string]interface{}{
				"internal_cidr":      "10.0.0.0/24",
				"network_name":       "some-network",
				"subnetwork_name":    "some-subnetwork",
				"bosh_open_tag_name": "some-jumpbox-tag",
				"jumpbox_tag_name":   "some-jumpbox-fw-tag",
				"external_ip":        "some-external-ip",
				"jumpbox_url":        "some-jumpbox-url",
				"some-key":           "some-value",
			}}

			state = storage.State{
				IAAS:  "gcp",
				EnvID: "some-env-id",
				GCP: storage.GCP{
					Zone:              "some-zone",
					ProjectID:         "some-project-id",
					ServiceAccountKey: "some-credential-json",
				},
				Jumpbox: storage.Jumpbox{
					Manifest: "name: jumpbox",
					State: map[string]interface{}{
						"some-key": "some-value",
					},
				},
			}

			deploymentVars = `internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.5
director_name: bosh-some-env-id
external_ip: some-external-ip
zone: some-zone
network: some-network
subnetwork: some-subnetwork
tags:
- some-jumpbox-tag
- some-jumpbox-fw-tag
project_id: some-project-id
gcp_credentials_json: some-credential-json
`

			createEnvArgs = []string{"bosh", "create-env", "/path/to/manifest.yml", "etc"}
			boshExecutor.CreateEnvCall.Returns.Variables = "jumpbox_ssh:\n  private_key: some-jumpbox-private-key"
		})

		AfterEach(func() {
			bosh.ResetOSSetenv()
		})

		Describe("InitializeJumpbox", func() {
			It("calls JumpboxCreateEnvArgsCall appropriately", func() {
				err := boshManager.InitializeJumpbox(state)
				Expect(err).NotTo(HaveOccurred())

				Expect(boshExecutor.JumpboxCreateEnvArgsCall.Receives.InterpolateInput.DeploymentDir).To(Equal("some-jumpbox-deployment-dir"))
				Expect(boshExecutor.JumpboxCreateEnvArgsCall.Receives.InterpolateInput.VarsDir).To(Equal("some-bbl-vars-dir"))
				Expect(boshExecutor.JumpboxCreateEnvArgsCall.Receives.InterpolateInput.StateDir).To(Equal("some-state-dir"))
			})

			Context("when an error occurs", func() {
				Context("when get vars dir fails", func() {
					It("returns an error", func() {
						stateStore.GetVarsDirCall.Returns.Error = errors.New("kiwi")

						err := boshManager.InitializeJumpbox(state)
						Expect(err).To(MatchError("Get vars dir: kiwi"))
					})
				})

				Context("when get deployment dir fails", func() {
					It("returns an error", func() {
						stateStore.GetJumpboxDeploymentDirCall.Returns.Error = errors.New("kiwi")

						err := boshManager.InitializeJumpbox(state)
						Expect(err).To(MatchError("Get deployment dir: kiwi"))
					})
				})
			})
		})

		Describe("CreateJumpbox", func() {
			It("starts a socks5 proxy for the duration of creating the bosh director", func() {
				socks5ProxyAddr := "localhost:1234"
				socks5Proxy.AddrCall.Returns.Addr = socks5ProxyAddr

				_, err := boshManager.CreateJumpbox(state, terraformOutputs)
				Expect(err).NotTo(HaveOccurred())

				Expect(osUnsetenvKey).To(Equal("BOSH_ALL_PROXY"))
				Expect(socks5Proxy.StartCall.CallCount).To(Equal(1))
				Expect(socks5Proxy.StartCall.Receives.JumpboxPrivateKey).To(Equal("some-jumpbox-private-key"))
				Expect(socks5Proxy.StartCall.Receives.JumpboxExternalURL).To(Equal("some-jumpbox-url"))
				Expect(osSetenvKey).To(Equal("BOSH_ALL_PROXY"))
				Expect(osSetenvValue).To(Equal(fmt.Sprintf("socks5://%s", socks5ProxyAddr)))

				Expect(logger.StepCall.Messages).To(gomegamatchers.ContainSequence([]string{
					"creating jumpbox",
					"created jumpbox",
					"starting socks5 proxy to jumpbox",
					"started proxy",
				}))
			})

			It("returns a bbl state with bosh and jumpbox deployment values", func() {
				state, err := boshManager.CreateJumpbox(state, terraformOutputs)
				Expect(err).NotTo(HaveOccurred())

				Expect(boshExecutor.CreateEnvCall.Receives.Input.VarsDir).To(Equal("some-bbl-vars-dir"))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.StateDir).To(Equal("some-state-dir"))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.Deployment).To(Equal("jumpbox"))
				Expect(boshExecutor.CreateEnvCall.Receives.Input.DeploymentVars).To(MatchYAML(`
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.5
director_name: bosh-some-env-id
external_ip: some-external-ip
zone: some-zone
network: some-network
subnetwork: some-subnetwork
tags:
- some-jumpbox-tag
- some-jumpbox-fw-tag
project_id: some-project-id
gcp_credentials_json: some-credential-json
bosh_open_tag_name: some-jumpbox-tag
jumpbox_tag_name: some-jumpbox-fw-tag
jumpbox_url: some-jumpbox-url
network_name: some-network
subnetwork_name: some-subnetwork
some-key: some-value
`))

				Expect(state).To(Equal(storage.State{
					IAAS:  "gcp",
					EnvID: "some-env-id",
					GCP: storage.GCP{
						Zone:              "some-zone",
						ProjectID:         "some-project-id",
						ServiceAccountKey: "some-credential-json",
					},
					Jumpbox: storage.Jumpbox{
						URL:   "some-jumpbox-url",
						State: nil,
					},
				}))
			})

			Context("when an error occurs", func() {
				Context("when geting the jumpbox key fails", func() {
					BeforeEach(func() {
						sshKeyGetter.GetCall.Returns.Error = errors.New("soursop")
					})

					It("returns an error", func() {
						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("jumpbox key: soursop"))
					})
				})

				Context("when get vars dir fails", func() {
					It("returns an error", func() {
						stateStore.GetVarsDirCall.Returns.Error = errors.New("kiwi")

						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("Get vars dir: kiwi"))
					})
				})

				Context("when create env returns a typed error", func() {
					It("returns an error", func() {
						boshExecutor.CreateEnvCall.Returns.Error = bosh.NewCreateEnvError(map[string]interface{}{"foo": "bar"}, errors.New("apple"))

						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("Create jumpbox env: apple"))
					})
				})

				Context("when create env returns an untyped error", func() {
					It("returns an error", func() {
						boshExecutor.CreateEnvCall.Returns.Error = errors.New("banana")

						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("Create jumpbox env: banana"))
					})
				})

				Context("when the socks5 proxy fails to start", func() {
					It("returns an error", func() {
						socks5Proxy.StartCall.Returns.Error = errors.New("coconut")

						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("Start proxy: coconut"))
					})
				})

				Context("when the socks5 proxy fails to return an address", func() {
					It("returns an error", func() {
						socks5Proxy.AddrCall.Returns.Error = errors.New("mango")

						_, err := boshManager.CreateJumpbox(state, terraformOutputs)
						Expect(err).To(MatchError("Get proxy address: mango"))
					})
				})
			})
		})
	})

	Describe("DeleteJumpbox", func() {
		var (
			vars          string
			incomingState storage.State
			jumpboxState  map[string]interface{}
		)
		BeforeEach(func() {
			vars = `jumpbox_ssh:
  private_key: some-private-key
  public_key: some-private-key
`

			jumpboxState = map[string]interface{}{
				"key": "value",
			}

			incomingState = storage.State{
				IAAS: "some-iaas",
				BOSH: storage.BOSH{
					Variables: "some-bosh-vars",
				},
				Jumpbox: storage.Jumpbox{
					Manifest: "some-manifest",
					State:    jumpboxState,
				},
			}
		})

		It("calls delete env", func() {
			err := boshManager.DeleteJumpbox(incomingState, terraform.Outputs{})
			Expect(err).NotTo(HaveOccurred())

			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.Deployment).To(Equal("jumpbox"))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.StateDir).To(Equal("some-state-dir"))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.VarsDir).To(Equal("some-bbl-vars-dir"))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.DeploymentVars).To(MatchYAML(`
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.5
director_name: bosh-`))

			Expect(boshExecutor.DeleteEnvCall.Receives.Input.Deployment).To(Equal("jumpbox"))
			Expect(boshExecutor.DeleteEnvCall.Receives.Input.VarsDir).To(Equal("some-bbl-vars-dir"))
			Expect(boshExecutor.DeleteEnvCall.Receives.Input.StateDir).To(Equal("some-state-dir"))
		})

		Context("when an error occurs", func() {
			Context("when the executor's delete env call fails with delete env error", func() {
				var expectedError bosh.ManagerDeleteError

				BeforeEach(func() {
					jumpboxState := map[string]interface{}{
						"partial": "jumpbox-state",
					}
					deleteEnvError := bosh.NewDeleteEnvError(jumpboxState, errors.New("failed to delete env"))
					boshExecutor.DeleteEnvCall.Returns.Error = deleteEnvError

					expectedState := incomingState
					expectedState.Jumpbox.State = jumpboxState
					expectedError = bosh.NewManagerDeleteError(expectedState, deleteEnvError)
				})

				It("returns a bosh manager delete error with a valid state", func() {
					err := boshManager.DeleteJumpbox(incomingState, terraform.Outputs{})
					Expect(err).To(MatchError(expectedError))
				})
			})

			Context("when the delete env fails", func() {
				BeforeEach(func() {
					boshExecutor.DeleteEnvCall.Returns.Error = errors.New("passionfruit")
				})

				It("returns an error", func() {
					err := boshManager.DeleteJumpbox(storage.State{}, terraform.Outputs{})
					Expect(err).To(MatchError("Delete jumpbox env: passionfruit"))
				})
			})
		})
	})

	Describe("DeleteDirector", func() {
		var varsDir string

		BeforeEach(func() {
			var err error
			varsDir, err = ioutil.TempDir("", "")
			Expect(err).NotTo(HaveOccurred())
			stateStore.GetVarsDirCall.Returns.Directory = varsDir
		})

		It("calls delete env", func() {
			socks5ProxyAddr := "localhost:1234"
			socks5Proxy.AddrCall.Returns.Addr = socks5ProxyAddr

			err := boshManager.DeleteDirector(storage.State{
				Jumpbox: storage.Jumpbox{
					URL: "some-jumpbox-url",
				},
				BOSH: storage.BOSH{
					Manifest: "some-manifest",
					State: map[string]interface{}{
						"key": "value",
					},
					Variables:   boshVars,
					UserOpsFile: "some-ops-file",
				},
			}, terraform.Outputs{})
			Expect(err).NotTo(HaveOccurred())

			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.Deployment).To(Equal("director"))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.StateDir).To(Equal("some-state-dir"))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.VarsDir).To(Equal(varsDir))
			Expect(boshExecutor.WriteDeploymentVarsCall.Receives.Input.DeploymentVars).To(MatchYAML(`
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.6
director_name: bosh-`))

			Expect(socks5Proxy.StartCall.CallCount).To(Equal(1))
			Expect(socks5Proxy.StartCall.Receives.JumpboxPrivateKey).To(Equal("some-jumpbox-private-key"))
			Expect(socks5Proxy.StartCall.Receives.JumpboxExternalURL).To(Equal("some-jumpbox-url"))

			Expect(osSetenvKey).To(Equal("BOSH_ALL_PROXY"))
			Expect(osSetenvValue).To(Equal(fmt.Sprintf("socks5://%s", socks5ProxyAddr)))

			Expect(boshExecutor.DeleteEnvCall.Receives.Input).To(Equal(bosh.DeleteEnvInput{
				Deployment: "director",
				StateDir:   "some-state-dir",
				VarsDir:    varsDir,
			}))
		})

		Context("when an error occurs", func() {
			var incomingState storage.State

			BeforeEach(func() {
				incomingState = storage.State{
					BOSH: storage.BOSH{
						Manifest: "some-manifest",
						State: map[string]interface{}{
							"key": "value",
						},
					},
					Jumpbox: storage.Jumpbox{},
				}
			})

			Context("when getting the jumpbox key fails", func() {
				BeforeEach(func() {
					sshKeyGetter.GetCall.Returns.Error = errors.New("rambutan")
				})

				It("returns an error", func() {
					err := boshManager.DeleteDirector(incomingState, terraform.Outputs{})
					Expect(err).To(MatchError("Delete bosh director: rambutan"))
				})
			})

			Context("when the executor's delete env call fails with delete env error", func() {
				It("returns a bosh manager delete error with a valid state", func() {
					boshState := map[string]interface{}{"partial": "bosh-state"}
					deleteEnvError := bosh.NewDeleteEnvError(boshState, errors.New("failed to delete env"))
					boshExecutor.DeleteEnvCall.Returns.Error = deleteEnvError

					expectedState := incomingState
					expectedState.BOSH = storage.BOSH{
						Manifest: "some-manifest",
						State:    boshState,
					}
					expectedError := bosh.NewManagerDeleteError(expectedState, deleteEnvError)
					err := boshManager.DeleteDirector(incomingState, terraform.Outputs{})
					Expect(err).To(MatchError(expectedError))
				})
			})

			Context("when the delete env fails", func() {
				BeforeEach(func() {
					boshExecutor.DeleteEnvCall.Returns.Error = errors.New("coconut")
				})

				It("returns an error", func() {
					err := boshManager.DeleteDirector(incomingState, terraform.Outputs{})
					Expect(err).To(MatchError("Delete director env: coconut"))
				})
			})

			Context("when a jumpbox deployment exists", func() {
				Context("when the socks5Proxy fails to start", func() {
					BeforeEach(func() {
						socks5Proxy.StartCall.Returns.Error = errors.New("failed to start socks5Proxy")
					})

					It("returns an error", func() {
						err := boshManager.DeleteDirector(incomingState, terraform.Outputs{})
						Expect(err).To(MatchError("Start socks5 proxy: failed to start socks5Proxy"))
					})
				})

				Context("when the socks5Proxy fails to return an address", func() {
					BeforeEach(func() {
						socks5Proxy.AddrCall.Returns.Error = errors.New("plum")
					})

					It("returns an error", func() {
						err := boshManager.DeleteDirector(incomingState, terraform.Outputs{})
						Expect(err).To(MatchError("Get proxy address: plum"))
					})
				})
			})
		})
	})

	Describe("GetJumpboxDeploymentVars", func() {
		Context("vsphere", func() {
			var incomingState storage.State
			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:    "vsphere",
					EnvID:   "some-env-id",
					VSphere: storage.VSphere{},
				}
			})
			It("returns a correct yaml string of bosh deployment variables", func() {
				vars := boshManager.GetJumpboxDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
					"internal_cidr":     "10.80.30.0/24",
					"external_ip":       "10.80.30.6",
					"network_name":      "plum",
					"vcenter_cluster":   "fruits",
					"vcenter_disks":     "plum",
					"vcenter_vms":       "plum_vms",
					"vcenter_templates": "plum_templates",
					"vcenter_user":      "user",
					"vcenter_password":  "password",
					"vcenter_ip":        "10.90.20.3",
					"vcenter_dc":        "fruits-dc",
					"vcenter_rp":        "plum",
					"vcenter_ds":        "fruits-ds",
				}})
				Expect(vars).To(MatchYAML(`---
director_name: bosh-some-env-id
internal_cidr: 10.80.30.0/24
internal_gw: 10.80.30.1
internal_ip: 10.80.30.5
external_ip: 10.80.30.6
network_name: plum
vcenter_rp: plum
vcenter_dc: fruits-dc
vcenter_ds: fruits-ds
vcenter_ip: 10.90.20.3
vcenter_user: user
vcenter_password: password
vcenter_templates: plum_templates
vcenter_vms: plum_vms
vcenter_disks: plum
vcenter_cluster: fruits`))
			})
		})

		Context("aws", func() {
			var incomingState storage.State
			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:    "aws",
					Jumpbox: storage.Jumpbox{},
					EnvID:   "some-env-id",
					AWS: storage.AWS{
						Region:          "some-region",
						AccessKeyID:     "some-access-key-id",
						SecretAccessKey: "some-secret-access-key",
					},
				}
			})

			It("returns a correct yaml string of bosh deployment variables", func() {
				vars := boshManager.GetJumpboxDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
					"some-key":               "some-value",
					"jumpbox_security_group": "some-security-group",
				}})
				Expect(vars).To(MatchYAML(`---
access_key_id: some-access-key-id
default_security_groups:
- "some-security-group"
director_name: bosh-some-env-id
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.5
jumpbox_security_group: some-security-group
region: some-region
secret_access_key: some-secret-access-key
some-key: some-value
`))
			})
		})

		Context("azure", func() {
			var incomingState storage.State
			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:    "azure",
					Jumpbox: storage.Jumpbox{},
					EnvID:   "some-env-id",
					Azure: storage.Azure{
						ClientID:       "some-client-id",
						ClientSecret:   "some-client-secret",
						SubscriptionID: "some-subscription-id",
						TenantID:       "some-tentant-id",
						Region:         "some-region",
					},
				}
			})

			It("returns a correct yaml string of bosh deployment variables", func() {
				vars := boshManager.GetJumpboxDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
					"internal_cidr":               "10.0.2.0/26",
					"bosh_network_name":           "some-network-name",
					"bosh_subnet_name":            "some-subnet-name",
					"bosh_resource_group_name":    "some-resource-group-name",
					"bosh_storage_account_name":   "some-storage-account-name",
					"bosh_default_security_group": "some-security-group",
					"bosh_vms_public_key":         "some-public-key",
					"bosh_vms_private_key":        "some-private-key",
					"some-key":                    "some-value",
				}})
				Expect(vars).To(MatchYAML(`---
bosh_default_security_group: some-security-group
bosh_network_name: some-network-name
bosh_resource_group_name: some-resource-group-name
bosh_storage_account_name: some-storage-account-name
bosh_subnet_name: some-subnet-name
bosh_vms_private_key: some-private-key
bosh_vms_public_key: some-public-key
client_id: some-client-id
client_secret: some-client-secret
default_security_group: some-security-group
director_name: bosh-some-env-id
internal_cidr: 10.0.2.0/26
internal_gw: 10.0.2.1
internal_ip: 10.0.2.5
private_key: some-private-key
public_key: some-public-key
resource_group_name: some-resource-group-name
some-key: some-value
storage_account_name: some-storage-account-name
subnet_name: some-subnet-name
subscription_id: some-subscription-id
tenant_id: some-tentant-id
vnet_name: some-network-name
`))
			})
		})

		Context("gcp", func() {
			var incomingState storage.State
			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:    "gcp",
					EnvID:   "some-env-id",
					Jumpbox: storage.Jumpbox{},
					GCP: storage.GCP{
						Zone:              "some-zone",
						ProjectID:         "some-project-id",
						ServiceAccountKey: "some-credential-json",
					},
				}
			})

			It("returns a correct yaml string of bosh deployment variables", func() {
				vars := boshManager.GetJumpboxDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
					"some-key":           "some-value",
					"bosh_open_tag_name": "some-jumpbox-tag",
					"jumpbox_tag_name":   "some-jumpbox-fw-tag",
				}})
				Expect(vars).To(MatchYAML(`---
bosh_open_tag_name: some-jumpbox-tag
director_name: bosh-some-env-id
gcp_credentials_json: some-credential-json
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.5
jumpbox_tag_name: some-jumpbox-fw-tag
project_id: some-project-id
some-key: some-value
tags:
- some-jumpbox-tag
- some-jumpbox-fw-tag
zone: some-zone
`))
			})
		})
	})

	Describe("GetDirectorDeploymentVars", func() {
		Context("gcp", func() {
			var incomingState storage.State
			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:  "gcp",
					EnvID: "some-env-id",
					GCP: storage.GCP{
						Zone:              "some-zone",
						ProjectID:         "some-project-id",
						ServiceAccountKey: "some-credential-json",
					},
					BOSH: storage.BOSH{
						State: map[string]interface{}{
							"some-key": "some-value",
						},
					},
				}
			})
			It("returns a correct yaml string of bosh deployment variables", func() {
				vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
					"some-key":                  "some-value",
					"internal_cidr":             "10.0.1.0/24",
					"bosh_director_tag_name":    "some-director-tag",
					"bosh_director_external_ip": "some-external-ip",
				}})
				Expect(vars).To(MatchYAML(`---
bosh_director_external_ip: some-external-ip
bosh_director_tag_name: some-director-tag
director_name: bosh-some-env-id
external_ip: some-external-ip
gcp_credentials_json: some-credential-json
internal_cidr: 10.0.1.0/24
internal_gw: 10.0.1.1
internal_ip: 10.0.1.6
project_id: some-project-id
some-key: some-value
tags:
- some-director-tag
zone: some-zone
`))
			})

			Context("when terraform outputs are missing", func() {
				It("returns valid yaml", func() {
					vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{})
					Expect(vars).To(MatchYAML(`---
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.6
director_name: bosh-some-env-id
zone: some-zone
tags:
- ""
project_id: some-project-id
gcp_credentials_json: some-credential-json
`))
				})
			})
		})

		Context("aws", func() {
			var incomingState storage.State

			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:  "aws",
					EnvID: "some-env-id",
					AWS: storage.AWS{
						AccessKeyID:     "some-access-key-id",
						SecretAccessKey: "some-secret-access-key",
						Region:          "some-region",
					},
					BOSH: storage.BOSH{
						State: map[string]interface{}{"some-key": "some-value"},
					},
				}
			})

			Context("when terraform was used to standup infrastructure", func() {
				It("returns a correct yaml string of bosh deployment variables", func() {
					vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
						"internal_cidr":                 "10.0.2.0/26",
						"bosh_iam_instance_profile":     "some-bosh-iam-instance-profile",
						"bosh_subnet_availability_zone": "some-bosh-subnet-az",
						"bosh_security_group":           "some-bosh-security-group",
						"bosh_subnet_id":                "some-bosh-subnet",
						"bosh_vms_key_name":             "some-keypair-name",
						"bosh_vms_private_key":          "some-private-key",
						"some-key":                      "some-value",
					}})
					Expect(vars).To(MatchYAML(`---
access_key_id: some-access-key-id
az: some-bosh-subnet-az
bosh_iam_instance_profile: some-bosh-iam-instance-profile
bosh_security_group: some-bosh-security-group
bosh_subnet_availability_zone: some-bosh-subnet-az
bosh_subnet_id: some-bosh-subnet
bosh_vms_key_name: some-keypair-name
bosh_vms_private_key: some-private-key
default_key_name: some-keypair-name
default_security_groups:
- some-bosh-security-group
director_name: bosh-some-env-id
iam_instance_profile: some-bosh-iam-instance-profile
internal_cidr: 10.0.2.0/26
internal_gw: 10.0.2.1
internal_ip: 10.0.2.6
private_key: some-private-key
region: some-region
secret_access_key: some-secret-access-key
some-key: some-value
subnet_id: some-bosh-subnet
`))
				})
			})

			Context("when terraform outputs are missing", func() {
				It("returns valid yaml", func() {
					vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{})
					Expect(vars).To(MatchYAML(`---
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.6
director_name: bosh-some-env-id
access_key_id: some-access-key-id
secret_access_key: some-secret-access-key
default_security_groups:
- ""
region: some-region
`))
				})
			})
		})

		Context("azure", func() {
			var incomingState storage.State

			BeforeEach(func() {
				incomingState = storage.State{
					IAAS:  "azure",
					EnvID: "some-env-id",
					Azure: storage.Azure{
						ClientID:       "some-client-id",
						ClientSecret:   "some-client-secret",
						SubscriptionID: "some-subscription-id",
						TenantID:       "some-tentant-id",
						Region:         "some-region",
					},
					BOSH: storage.BOSH{
						State: map[string]interface{}{"some-key": "some-value"},
					},
				}
			})

			Context("when terraform was used to standup infrastructure", func() {
				It("returns a correct yaml string of bosh deployment variables", func() {
					vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{Map: map[string]interface{}{
						"internal_cidr":               "10.0.2.0/26",
						"bosh_iam_instance_profile":   "some-bosh-iam-instance-profile",
						"bosh_network_name":           "some-network-name",
						"bosh_subnet_name":            "some-subnet-name",
						"bosh_resource_group_name":    "some-resource-group-name",
						"bosh_storage_account_name":   "some-storage-account-name",
						"bosh_default_security_group": "some-security-group",
						"some-key":                    "some-value",
					}})
					Expect(vars).To(MatchYAML(`---
bosh_default_security_group: some-security-group
bosh_iam_instance_profile: some-bosh-iam-instance-profile
bosh_network_name: some-network-name
bosh_resource_group_name: some-resource-group-name
bosh_storage_account_name: some-storage-account-name
bosh_subnet_name: some-subnet-name
client_id: some-client-id
client_secret: some-client-secret
default_security_group: some-security-group
director_name: bosh-some-env-id
internal_cidr: 10.0.2.0/26
internal_gw: 10.0.2.1
internal_ip: 10.0.2.6
resource_group_name: some-resource-group-name
some-key: some-value
storage_account_name: some-storage-account-name
subnet_name: some-subnet-name
subscription_id: some-subscription-id
tenant_id: some-tentant-id
vnet_name: some-network-name
`))
				})
			})

			Context("when terraform outputs are missing", func() {
				It("returns valid yaml", func() {
					vars := boshManager.GetDirectorDeploymentVars(incomingState, terraform.Outputs{})
					Expect(vars).To(MatchYAML(`---
client_id: some-client-id
client_secret: some-client-secret
director_name: bosh-some-env-id
internal_cidr: 10.0.0.0/24
internal_gw: 10.0.0.1
internal_ip: 10.0.0.6
subscription_id: some-subscription-id
tenant_id: some-tentant-id
`))
				})
			})
		})
	})

	Describe("Version", func() {
		BeforeEach(func() {
			boshExecutor.VersionCall.Returns.Version = "2.0.24"
		})

		It("calls out to bosh executor version", func() {
			version, err := boshManager.Version()
			Expect(err).NotTo(HaveOccurred())
			Expect(boshExecutor.VersionCall.CallCount).To(Equal(1))
			Expect(version).To(Equal("2.0.24"))
		})

		Context("when executor returns a bosh version error", func() {
			var expectedError bosh.BOSHVersionError
			BeforeEach(func() {
				boshExecutor.VersionCall.Returns.Version = ""
				expectedError = bosh.NewBOSHVersionError(errors.New("BOSH version could not be parsed"))
				boshExecutor.VersionCall.Returns.Error = expectedError
			})

			It("logs a warning and returns the error", func() {
				version, err := boshManager.Version()

				Expect(boshExecutor.VersionCall.CallCount).To(Equal(1))
				Expect(logger.PrintlnCall.CallCount).To(Equal(1))
				Expect(err).To(Equal(expectedError))
				Expect(version).To(Equal(""))
			})
		})

		Context("when executor fails", func() {
			BeforeEach(func() {
				boshExecutor.VersionCall.Returns.Error = errors.New("failed to execute")
			})

			It("returns an error", func() {
				_, err := boshManager.Version()
				Expect(err).To(MatchError("failed to execute"))
			})
		})
	})
})


text:
module.exports = makeListener;

function makeListener(host) {
  var currentAnswers = {};
  var userCallback;

  return {
    listen: listen,
    cancel: reset
  };

  function listen(answers, callback) {
    if (!Array.isArray(answers)) {
      throw new Error('answers must be an Array');
    }

    if (typeof callback != 'function') {
      throw new Error('callback must be a function');
    }

    reset();

    answers.forEach(function(answer) {
      createGetter(host, answer);

      currentAnswers[answer] = answer;
    });

    userCallback = callback;
  }

  function createGetter(host, answer) {
    if (answer in host) {
      throw new Error('Property is already defined on host object, host[\'' + answer + '\'] is: ' + host[answer]);
    }

    Object.defineProperty(host, answer, {
      get: function() {
        runCallbackForAnswer(answer);
      },
      configurable: true
    });
  }

  function runCallbackForAnswer(answer) {
    if (answer in currentAnswers) {
      userCallback(answer);
      reset();
    }
  }

  function reset() {
    for (var answer in currentAnswers) {
      delete host[answer];
    }

    currentAnswers = {};
    userCallback = null;
  }
}

redpajama_set_name: RedPajamaGithub


text:
<?php
return array (
  'Mark all as seen' => 'Oznacz wszystkie jako przeczytane ',
  'Notifications' => 'Powiadomienia ',
  'There are no notifications yet.' => 'Nie ma jeszcze powiadomień. ',
);


text:
package com.brightgenerous.orm;

import static com.brightgenerous.commons.ObjectUtils.*;
import static com.brightgenerous.orm.ICloneable.Utils.*;

import java.io.Serializable;

import com.brightgenerous.commons.EqualsUtils;
import com.brightgenerous.commons.HashCodeUtils;
import com.brightgenerous.commons.ToStringUtils;

public class Option<T extends Serializable> implements Clearable, EmptyChackable,
        ICloneable<Option<T>>, Serializable {

    private static final long serialVersionUID = 2675962143167865812L;

    private final UpdatedCallback callback;

    private T value;

    protected Option(UpdatedCallback callback) {
        this.callback = callback;
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        if (!equalsValueOrNull(this.value, value)) {
            this.value = value;
            callbackUpdated();
        }
    }

    @Override
    public boolean isEmpty() {
        return getValue() == null;
    }

    @Override
    public void clear() {
        boolean changed = false;
        if (value != null) {
            value = null;
            changed |= true;
        }
        if (changed) {
            callbackUpdated();
        }
    }

    @Override
    public Option<T> clone() {
        Option<T> ret;
        try {
            ret = (Option<T>) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
        ret.value = getIfClone(value);
        return ret;
    }

    private void callbackUpdated() {
        if (callback != null) {
            callback.updated();
        }
    }

    @Override
    public int hashCode() {
        if (HashCodeUtils.resolved()) {
            return HashCodeUtils.hashCodeAlt(null, this);
        }
        return super.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (EqualsUtils.resolved()) {
            return EqualsUtils.equalsAlt(null, this, obj);
        }
        return super.equals(obj);
    }

    @Override
    public String toString() {
        if (ToStringUtils.resolved()) {
            return ToStringUtils.toStringAlt(this);
        }
        return super.toString();
    }
}


text:
<?php

namespace Roave\DeveloperTools\Mvc\Factory;

use Roave\DeveloperTools\Mvc\Inspector\ConfigInspector;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

/**
 * Factory responsible for instantiating a {@see \Roave\DeveloperTools\Mvc\Inspector\ConfigInspector}
 * that inspects the application's merged config
 */
class MergedConfigInspectorFactory implements FactoryInterface
{
    /**
     * {@inheritDoc}
     *
     * @return ConfigInspector
     */
    public function createService(ServiceLocatorInterface $serviceLocator)
    {
        return new ConfigInspector($serviceLocator, 'Config');
    }
}


text:
const { promptArgs, checkName } = require('../../promptUtils');

const prompt = async ({ prompter, args }) => {
  let questions = [];

  if (!args.name) {
    questions.push({
      type: 'input',
      name: 'name',
      message: 'Name:',
    });
  }

  let { name } = await promptArgs({ prompter, args, questions });
  name = checkName(name, 'Model');

  return { name };
};

module.exports = {
  prompt,
};


text:
@interface PodsDummy_Pods_CJPopupActionDemo : NSObject
@end
@implementation PodsDummy_Pods_CJPopupActionDemo
@end


text:
using System;
using System.Diagnostics;
using System.IO;

namespace Symbooglix
{
    public struct ExecutorStatistics : Util.IYAMLWriter
    {
        public TimeSpan RunTime;
        public TimeSpan PrepareTime;
        public int InstructionsExecuted;
        public int ForkCount;
        public Executor.ExecutorTerminationType TerminationType;

        public void Reset()
        {
            this.RunTime = TimeSpan.Zero;
            this.PrepareTime = TimeSpan.Zero;
            this.InstructionsExecuted = 0;
            this.ForkCount = 0;
            TerminationType = Executor.ExecutorTerminationType.UNKNOWN;
        }

        public override string ToString()
        {
            string result;
            using (var SW = new StringWriter())
            {
                using (var ITW = new System.CodeDom.Compiler.IndentedTextWriter(SW))
                {
                    WriteAsYAML(ITW);
                }
                result = SW.ToString();
            }
            return result;
        }

        public void WriteAsYAML(System.CodeDom.Compiler.IndentedTextWriter TW)
        {
            TW.WriteLine("#Executor statistics as YAML. Times are in seconds");
            TW.WriteLine("prepare_time: {0}", PrepareTime.TotalSeconds);
            TW.WriteLine("run_time: {0}", RunTime.TotalSeconds);
            TW.WriteLine("instructions_executed: {0}", InstructionsExecuted);
            TW.WriteLine("num_forks: {0}", ForkCount);
            TW.WriteLine("termination_type: \"{0}\"", TerminationType.ToString());
        }
    }
}


text:
\weblink{https://www.fanfiction.net/s/5782108/18/}
\chapter{Chapter 18: Dominance Hierarchies}
Any sufficiently advanced J. K. Rowling is indistinguishable from magic.

\begin{center}\rule{3in}{0.4pt}\end{center}

\emph{``That does sound like the sort of thing I would do, doesn't it?''}

\begin{center}\rule{3in}{0.4pt}\end{center}

It was breakfast time on Friday morning. Harry took another huge bite out of his toast and then tried to remind his brain that scarfing his breakfast wouldn't actually get him into the dungeons any faster. Anyway they had a full hour of study time between breakfast and the start of Potions.

But dungeons! In Hogwarts! Harry's imagination was already sketching the chasms, narrow bridges, torchlit sconces, and patches of glowing moss. Would there be rats? Would there be \emph{dragons?}

``Harry Potter,'' said a quiet voice from behind him.

Harry looked over his shoulder and found himself beholding Ernie Macmillan, smartly dressed in yellow-trimmed robes and looking a little worried.

``Neville thought I should warn you,'' Ernie said in a low voice. ``I think he's right. Be careful of the Potions Master in our session today. The older Hufflepuffs told us that Professor Snape can be really nasty to people he doesn't like, and he doesn't like most people who aren't Slytherins. If you say anything smart to him it... it could be really bad for you, from what I've heard. Just keep your head down and don't give him any reason to notice you.''

There was a pause as Harry processed this, and then he lifted his eyebrows. (Harry wished he could raise just one eyebrow, like Spock, but he'd never been able to manage.) ``Thanks,'' Harry said. ``You might've just saved me a lot of trouble.''

Ernie nodded, and turned to go back to the Hufflepuff table.

Harry resumed eating his toast.

It was around four bites afterward that someone said ``Pardon me,'' and Harry turned around to see an older Ravenclaw, looking a little worried -

Some time later, Harry was finishing up his third plate of rashers. (He'd learned to eat heavily at breakfast. He could always eat lightly at lunch if he didn't end up using the Time-Turner.) And there was yet another voice from behind him saying ``Harry?''

``Yes,'' Harry said wearily, ``I'll try not to draw Professor Snape's attention~-''

``Oh, that's hopeless,'' said Fred.

``Completely hopeless,'' said George.

``So we had the house elves bake you a cake,'' said Fred.

``We're going to put one candle on it for every point you lose for Ravenclaw,'' said George.

``And have a party for you at the Gryffindor table during lunch,'' said Fred.

``We hope that'll cheer you up afterward,'' finished George.

Harry swallowed his last bite of rasher and turned around. ``All right,'' said Harry. ``I wasn't going to ask this after Professor Binns, I really wasn't, but if Professor Snape is \emph{that} awful why hasn't he been fired?''

``Fired?'' said Fred.

``You mean, let go?'' said George.

``Yes,'' Harry said. ``It's what you do to bad teachers. You fire them. Then you hire a better teacher instead. You don't have unions or tenure here, right?''

Fred and George were frowning in much the same way that hunter-gatherer tribal elders might frown if you tried to tell them about calculus.

``I don't know,'' said Fred after a while. ``I never thought about that.''

``Me neither,'' said George.

``Yeah,'' said Harry, ``I get that a lot. See you at lunch, guys, and don't blame me if there aren't any candles on that cake.''

Fred and George both laughed, as if Harry had said something funny, and bowed to him and headed back toward Gryffindor.

Harry turned back to the breakfast table and grabbed a cupcake. His stomach already felt full, but he had a feeling this morning might use a lot of calories.

As he ate his cupcake, Harry thought of the worst teacher he'd met so far, Professor Binns of History. Professor Binns was a ghost. From what Hermione had said about ghosts, it didn't seem likely that they were fully self-aware. There were no famous discoveries made by ghosts, or much of any original work, no matter who they'd been in life. Ghosts tended to have trouble remembering the current century. Hermione had said they were like accidental portraits, impressed into the surrounding matter by a burst of psychic energy accompanying a wizard's sudden death.

Harry had run into some stupid teachers during his abortive forays into standard Muggle education~--- his father had been a lot pickier when it came to selecting grad students as tutors, of course~--- but History class was the first time he'd encountered a teacher who literally wasn't sentient.

And it showed, too. Harry had given up after five minutes and started reading a textbook. When it became clear that ``Professor Binn s'' wasn't going to object, Harry had also reached into his pouch and gotten earplugs.

Did ghosts not require a salary? Was that it? Or was it literally impossible to fire anyone in Hogwarts \emph{even if they died?}

Now it seemed that Professor Snape was going about being absolutely awful to everyone who wasn't a Slytherin and it hadn't even \emph{occurred} to anyone to terminate his contract.

And the Headmaster had set fire to a chicken.

``Excuse me,'' came a worried voice from behind him.

``I swear,'' Harry said without turning around, ``this place is almost eight and a half percent as bad as what Dad says about Oxford.''

\begin{center}\rule{3in}{0.4pt}\end{center}

Harry stamped down the stone corridors, looking affronted, annoyed, and infuriated all at once.

``Dungeons!'' Harry hissed. ``\emph{Dungeons!} These are not dungeons! This is a basement! A \emph{basement!}''

Some of the Ravenclaw girls gave him odd looks. The boys were all used to him by now.

It seemed that the level in which the Potions classroom was located was called the ``dungeon s'' for no better reason than that it was below ground and slightly colder than the main castle.

In \emph{Hogwarts!} In \emph{Hogwarts!} Harry had been waiting his whole life and now he was \emph{still} waiting and if there was anywhere \emph{on the face of the Earth} that had decent dungeons it ought to be Hogwarts! Was Harry going to have to build his own castle if he wanted to see one little bottomless abyss?

A short time later they got to the actual Potions classroom and Harry cheered up considerably.

The Potions classroom had strange preserved creatures floating in huge jars on shelves that covered every centimeter of wall space between the closets. Harry had gotten far enough along in his reading now that he could actually identify some of the creatures, like the Zabriskan Fontema. Albeit the fifty-centimeter spider \emph{looked} like an Acromantula but it was too small to \emph{be} one. He'd tried asking Hermione, but she hadn't seemed very interested in looking anywhere near where he was pointing.

Harry was looking at a large dust ball with eyes and feet when the assassin swept into the room.

That was the first thought that crossed Harry's mind when he saw Professor Severus Snape. There was something quiet and deadly about the way the man stalked between the children's desks. His robes were unkempt, his hair spotted and greasy. There was something about him that seemed reminiscent of Lucius, although the two of them looked nothing remotely alike, and you got the impression that where Lucius would kill you with flawless elegance, this man would simply kill you.

``Sit down,'' said Professor Severus Snape. ``Now.''

Harry and a few other children who had been standing around talking to each other scrambled for desks. Harry had planned on ending up next to Hermione but somehow he found himself sitting down in the nearest empty desk next to Justin Finch-Fletchley (it was a Doubles session, Ravenclaw and Hufflepuff) which put him two desks to the left of Hermione.

Severus seated himself behind the teacher's desk, and without the slightest transition or introduction, said, ``Hannah Abbott.''

``Here,'' said Hannah in a somewhat trembling voice.

``Susan Bones.''

``Present.''

And so it went, no one daring to say a word in edgewise, until:

``Ah, yes. Harry Potter. Our new... \emph{celebrity.}''

``The celebrity is present, \emph{sir}.''

Half the class flinched, and some of the smarter ones suddenly looked like they wanted to run out the door while the classroom was still there.

Severus smiled in an anticipatory sort of way and called the next name on his list.

Harry gave a mental sigh. That had happened way too fast for him to do anything about it. Oh well. Clearly this man already didn't like him, for whatever reason. And when Harry thought about it, better by far that this Potions professor should pick on \emph{him} rather than, say, Neville or Hermione. Harry was a lot better able to defend himself. Yep, probably all for the best.

When full attendance had been taken, Severus swept his gaze over the full class. His eyes were as empty as a night sky without stars.

``You are here,'' Severus said in a quiet voice which the students at back strained to hear, ``to learn the subtle science and exact art of potionmaking. As there is little foolish wand-waving here, many of you will hardly believe this is magic. I don't expect you will really understand the beauty of the softly simmering cauldron with its shimmering fumes, the delicate power of liquids that creep through human veins,'' this in a rather caressing, gloating tone, ``bewitching the mind, ensnaring the senses,'' this was just getting creepier and creepier. ``I can teach you how to bottle fame, brew glory, even stopper death~--- if you aren't as great a pack of fools as I usually have to teach.''

Severus somehow seemed to notice the look of skepticism on Harry's face, or at least his eyes suddenly jumped to where Harry was sitting.

``Potter!'' snapped the Potions professor. ``What would I get if I added powdered root of asphodel to an infusion of wormwood?''

Harry blinked. ``Was that in \emph{Magical Drafts and Potions}?'' he said. ``I just finished reading it, and I don't remember anything which used wormwood~-''

Hermione's hand went up and Harry shot her a glare which caused her to raise her hand even higher.

``Tut, tut,'' Severus said silkily. ``Fame clearly isn't everything.''

``Really?'' Harry said. ``But you just told us you'd teach us how to bottle fame. Say, how \emph{does} that work, exactly? You drink it and turn into a celebrity?''

Three-quarters of the class flinched.

Hermione's hand was dropping slowly back down. Well, that wasn't surprising. She might be his rival, but she wasn't the sort of girl who would play along after it became clear that the professor was deliberately trying to humiliate him.

Harry was trying hard to keep control of his temper. The first rejoinder that had crossed his mind was `Abracadabra'.

``Let's try again,'' said Severus. ``Potter, where would you look if I told you to find me a bezoar?''

``That's not in the textbook either,'' Harry said, ``but in one Muggle book I read that a trichinobezoar is a mass of solidified hair found in a human stomach, and Muggles used to believe it would cure any poison~-''

``Wrong,'' Severus said. ``A bezoar is found in the stomach of a goat, it is not made of hair, and it will cure most poisons but not all.''

``I didn't \emph{say} it would, I said that was what I read in one Muggle book~-''

``No one here is interested in your \emph{pathetic} Muggle books. Final try. What is the difference, Potter, between monksblood and wolfsbane?''

That did it.

``You know,'' Harry said icily, ``in one of my quite \emph{fascinating} Muggle books, they describe a study in which people managed to make themselves look very smart by asking questions about random facts that only they knew. Apparently the onlookers only noticed that the askers knew and the answerers didn't, and failed to adjust for the unfairness of the underlying game. So, Professor, can you tell me how many electrons are in the outermost orbital of a carbon atom?''

Severus's smile widened. ``Four,'' he said. ``It is a useless fact which no one should bother writing down, however. And for your information, Potter, asphodel and wormwood make a sleeping potion so powerful it is known as the Draught of Living Death. As for monkshood and wolfsbane, they are the same plant, which also goes by the name of aconite, as you would know if you had read \emph{One Thousand Magical Herbs and Fungi.} Thought you didn't need to open the book before coming, eh, Potter? All the rest of you should be copying that down so that you will not be as ignorant as him.'' Severus paused, looking quite pleased with himself. ``And that will be... five points? No, let us make it an even ten points from Ravenclaw for backchat.''

Hermione gasped, along with a number of others.

``Professor Severus Snape,'' Harry bit out. ``I know of nothing which I have done to earn your enmity. If there is some problem you have with me which I do not know about, I suggest we~-''

``Shut up, Potter. Ten more points from Ravenclaw. The rest of you, open your books to page 3.''

There was only a slight, only a very faint burning sensation in the back of Harry's throat, and no moisture at all in his eyes. If crying was not an effective strategy for destroying this Potions professor then there was no point in crying.

Slowly, Harry sat up very straight. All his blood seemed to have been drained away and replaced with liquid nitrogen. He knew he'd been trying to keep his temper but he couldn't seem to remember why.

``Harry,'' whispered Hermione frantically from two desks over, ``stop, please, it's all right, we won't count it~-''

``Talking in class, Granger? Three~-''

``So,'' said a voice colder than zero Kelvin, ``how does one go about filing a formal complaint against an abusive professor? Does one talk to the Deputy Headmistress, write a letter to the Board of Governors... would you care to explain how it works?''

The class was utterly frozen.

``Detention for one month, Potter,'' Severus said, smiling even more broadly.

``I decline to recognize your authority as a teacher and I will not serve any detention you give.''

People stopped breathing.

Severus's smile vanished. ``Then you will be~-'' his voice stopped short.

``Expelled, were you about to say?'' Harry, on the other hand, was now smiling thinly. ``But then you seemed to doubt your ability to carry out the threat, or fear the consequences if you did. I, on the other hand, neither doubt nor fear the prospect of finding a school with less abusive professors. Or perhaps I should hire private tutors, as is my accustomed practice, and be taught at my full learning speed. I have enough money in my vault. Something about bounties on a Dark Lord I defeated. But there \emph{are} teachers at Hogwarts who I rather like, so I think it will be easier if I find some way to get rid of you instead.''

``Get rid of me?'' Severus said, now also smiling thinly. ``What an amusing conceit. How do you suppose you will do that, Potter?''

``I understand there have been a number of complaints about you from students and their parents,'' a guess but a safe one, ``which leaves only the question of why you're not already gone. Is Hogwarts too financially strapped to afford a real Potions professor? I could chip in, if so. I'm sure they could find a better class of teacher if they offered double your current salary.''

Two poles of ice radiated freezing winter across the classroom.

``You will find,'' Severus said softly, ``that the Board of Governers is not the slightest bit sympathetic to your offer.''

``Lucius...'' Harry said. ``\emph{That's} why you're still here. Perhaps I should chat with Lucius about that. I believe he desires to meet with me. I wonder if I have anything he wants?''

Hermione frantically shook her head. Harry noticed out of the corner of his eye, but his attention was all on Severus.

``You are a very foolish boy,'' Severus said. He wasn't smiling at all, now. ``You have nothing that Lucius values more than my friendship. And if you did, I have other allies.'' His voice grew hard. ``And I find it increasingly unlikely that you were not Sorted into Slytherin. How was it that you managed to stay out of my House? Ah, yes, because the Sorting Hat claimed it was \emph{joking}. For the first time in recorded history. What were you really \emph{chatting} about with the Sorting Hat, Potter? Did you have something that it wanted?''

Harry stared into Severus's cold gaze and remembered that the Sorting Hat had warned him not to meet anyone's eyes while thinking about~--- Harry dropped his gaze to Severus's desk.

``You seem oddly reluctant to look me in the eyes, Potter!''

A shock of sudden understanding~--- ``So it was \emph{you} the Sorting Hat was warning me about!''

``What?'' said Severus's voice, sounding genuinely surprised, though of course Harry didn't look at his face.

Harry got up out of his desk.

``Sit down, Potter,'' said an angry voice from somewhere he wasn't looking.

Harry ignored it, and looked around the classroom. ``I have no intention of letting one unprofessional teacher ruin my time at Hogwarts,'' Harry said with deadly calm. ``I think I'll take my leave of this class, and either hire a tutor to teach me Potions while I'm here, or if the Board is really that locked up, learn over the summer. If any of you decide that you don't care to be bullied by this man, my sessions will be open to you.''

``\emph{Sit down, Potter!}''

Harry strode across the room and grasped the doorknob.

It didn't turn.

Harry slowly turned around, and caught a glimpse of Severus smiling nastily before he remembered to look away.

``Open this door.''

``No,'' said Severus.

``You are making me feel threatened,'' said a voice so icy it didn't sound like Harry's at all, ``and that is a mistake.''

Severus's voice laughed. ``What do you intend to do about it, little boy?''

Harry took six long strides forward away from the door, until he was standing near the back row of desks.

Then Harry drew himself upright and raised his right hand in one terrible motion, fingers poised to snap.

Neville screamed and dived under his desk. Other children shrank back or instinctively raised their arms to shield themselves.

``\emph{Harry don't!}'' shrieked Hermione. ``Whatever you were going to do to him, don't do it!''

``Have you all gone \emph{mad?}'' barked Severus's voice.

Slowly, Harry lowered his hand. ``I wasn't going to hurt him, Hermione,'' Harry said, his voice a little lower. ``I was just going to blow up the door.''

Though now that Harry remembered it, you weren't supposed to Transfigure things that were to be burned, which meant that going back in time afterward and getting Fred or George to Transfigure some carefully measured amount of explosives might not actually have been such a good idea...

``\emph{Silencio,}'' said Severus's voice.

Harry tried to say ``What?'' and found that no sound was coming out.

``This has become ridiculous. I think you've been allowed to get yourself in enough trouble for one day, Potter. You are the most disruptive and unruly student I have ever seen, and I don't recall how many points Ravenclaw has right now, but I'm sure I can manage to wipe them all out. Ten points from Ravenclaw. Ten points from Ravenclaw. Ten points from Ravenclaw! Fifty points from Ravenclaw! Now sit down and watch the rest of the class take their lesson!''

Harry put his hand into his pouch and tried to say `marker' but of course no words came out. For one brief moment that stopped him; and then it occurred to Harry to spell out M-A-R-K-E-R using finger motions, which worked. P-A-D and he had a pad of paper. Harry strode over to an empty desk, not the one he'd originally sat down in, and scrawled a brief message. He tore off that sheet of paper, put away the marker and pad in a pocket of his robes for quicker access, and held up his message, not to Snape, but to the rest of the class.

I'M LEAVING

DOES ANYONE ELSE

NEED TO GET OUT?

``You're insane, Potter,'' Severus said with cold contempt.

Aside from that, no one spoke.

Harry swept an ironic bow to the teacher's desk, walked over to the wall, and with one smooth motion yanked open a closet door, stepped in, and slammed the door shut behind him.

There was the muffled sound of someone snapping his fingers, and then nothing.

In the classroom, students looked at each other in puzzlement and fear.

The Potions Master's face was now completely enraged. He crossed the room in terrible strides and yanked open the closet door.

The closet was empty.

\begin{center}\rule{3in}{0.4pt}\end{center}

One hour earlier, Harry listened from inside the closed closet. There was no sound from outside, and no point in taking risks either.

C-L-O-A-K, his fingers spelled out.

Once he was invisible, he very carefully and slowly cracked open the closet door and peeked out. No one seemed to be in the classroom.

The door wasn't locked.

It was when Harry was outside the dangerous place and inside the hallway, safely invisible, that some of the anger drained away and he realized what he'd just done.

What he'd just done.

Harry's invisible face was frozen in absolute horror.

He'd antagonized a teacher three orders of magnitude beyond anything he'd ever managed before. He'd threatened to walk out of Hogwarts and might have to follow through on it. He'd lost all the points Ravenclaw had and then he'd used the Time-Turner...

His imagination showed him his parents yelling at him after he was expelled, Professor McGonagall disappointed in him, and it was just too painful and he couldn't bear it and he \emph{couldn't think of any way to save himself -}

The thought that Harry allowed himself to think was that if getting angry had gotten him into all this trouble, then maybe when he was angry he'd think of a way out, things seemed clearer somehow when he was angry.

And the thought that Harry didn't let himself think was that he just couldn't face this future if he wasn't angry.

So he cast his thoughts back and remembered the burning humiliation -

\emph{Tut, tut. Fame clearly isn't everything.}

\emph{Ten points from Ravenclaw for backchat.}

The calming cold washed back through his veins like a wave reflected and returning from some breaker, and Harry let out his breath.

Okay. Back to being sane now.

He was actually feeling a bit disappointed in his non-angry self for collapsing like that and wanting only to get out of trouble. Professor Severus Snape was \emph{everyone's} problem. Normal-Harry had forgotten that and wished for a way to protect \emph{himself.} And let all the other victims go hang? The question wasn't how to protect himself, the question was how to destroy this Potions professor.

\emph{So this is my dark side, is it?} \emph{Bit of a prejudiced term that, my light side seems more selfish and cowardly, not to mention confused and panicky.}

And now that he was thinking clearly, it was equally clear what to do next. He'd already given himself an extra hour to prepare, and could get up to five hours more if required...

\begin{center}\rule{3in}{0.4pt}\end{center}

Minerva McGonagall waited in the Headmaster's office.

Dumbledore sat in his padded throne behind his desk, dressed in four layers of formal lavender robes. Minerva sat in a chair before him, opposite Severus in another chair. Facing the three of them was an empty wooden stool.

They were waiting for Harry Potter.

\emph{Harry,} Minerva thought despairingly, \emph{you promised you wouldn't bite any teachers!}

And in her mind she could see very clearly the reply, Harry's angry face and his outraged response: \emph{I said I wouldn't bite anyone who didn't bite me first!}

There was a knock at the door.

``Come in!'' Dumbledore called.

The door swept open, and Harry Potter entered. Minerva almost gasped out loud. The boy looked cool, collected, and utterly in control of himself.

``Good mor~-'' Harry's voice suddenly cut off. His jaw dropped.

Minerva tracked Harry's gaze, and she saw that Harry was staring at Fawkes where the phoenix sat on its golden perch. Fawkes fluttered his bright red-golden wings like the flickering of a flame, and dipped his head in a measured nod to the boy.

Harry turned to stare at Dumbledore.

Dumbledore winked at him.

Minerva felt she was missing something.

Sudden uncertainty crossed Harry's face. His coolness wavered. Fear showed in his eyes, then anger, and then the boy was calm again.

A chill went down Minerva's spine. Something was not right here.

``Please sit down,'' said Dumbledore. His face was now serious once more.

Harry sat.

``So, Harry,'' said Dumbledore. ``I've heard one report of this day from Professor Snape. Would you care to tell me what happened in your own words?''

Harry's gaze flicked dismissively to Severus. ``It's not complicated,'' said the boy, smiling thinly. ``He tried bullying me the way he's been bullying every non-Slytherin in the school since the day Lucius foisted him off on you. As for the other details, I request a private conversation with you concerning them. A student who is reporting abusive behavior from a professor can hardly be expected to speak frankly in front of that same professor, after all.''

This time Minerva couldn't stop herself from gasping out loud.

Severus simply laughed.

And the Headmaster's face grew grave. ``Mr. Potter,'' the Headmaster said, ``one does not speak of a Hogwarts professor in such terms. I fear that you labor under a terrible misapprehension. Professor Severus Snape has my fullest confidence, and serves Hogwarts at my own behest, not Lucius Malfoy's.''

There was silence for a few moments.

When the boy spoke again his voice was icy. ``Am I missing something here?''

``Quite a number of things, Mr. Potter,'' said the Headmaster. ``You should understand, to start with, that the purpose of this meeting is to discuss how to discipline you for the events of this morning.''

``This man has terrorized your school for years. I spoke to students and collected stories to make sure there would be enough for a newspaper campaign to rally the parents against him. Some of the younger students cried while they told me. I almost cried when I heard them! \emph{You allowed this abuser to run free? You did this to your students? Why?}''

Minerva swallowed a lump in her throat. She'd~--- thought that, sometimes, but somehow she'd never quite -

``Mr. Potter,'' said the Headmaster, his voice now stern, ``this meeting is not about Professor Snape. It is about you and your disregard for school discipline. Professor Snape has suggested, and I have agreed, that three full months of detention will be appropriate~-''

``Declined,'' Harry said icily.

Minerva was speechless.

``This is not a request, Mr. Potter,'' the Headmaster said. The full, entire force of the wizard's gaze was turned on the boy. ``This is your punishme~-''

``You will explain to me why you allowed this man to hurt the children placed in your care, and if your explanation is not sufficient then I will begin my newspaper campaign with \emph{you} as the target.''

Minerva's body swayed with the force of that blow, with the sheer raw \emph{lese majeste}.

Even Severus looked shocked.

``That, Harry, would be most extremely unwise,'' Dumbledore said slowly. ``I am the primary piece opposing Lucius on the gameboard. For you to do such a thing would strengthen him greatly, and I did not think that was your chosen side.''

The boy was still for a long moment.

``This conversation grows private,'' Harry said. His hand flicked in Severus's direction. ``Send him away.''

Dumbledore shook his head. ``Harry, did I not tell you that Severus Snape has my fullest confidence?''

The boy's face showed the shock of it. ``This man's bullying makes you vulnerable! I am not the only one who could start a newspaper campaign against you! This is insane! Why are you doing this?''

Dumbledore sighed. ``I'm sorry, Harry. It has to do with things that you are not, at this time, ready to hear.''

The boy stared at Dumbledore. Then he turned to look at Severus. Then back to Dumbledore again.

``It \emph{is} insanity,'' the boy said slowly. ``You haven't reined him in because you think he's \emph{part of the pattern}. That Hogwarts needs an evil Potions Master to be a proper magical school, just as it needs a ghost to teach History.''

``That does sound like the sort of thing I would do, doesn't it?'' said Dumbledore, smiling.

``Unacceptable,'' Harry said flatly. His gaze was now cold and dark. ``I will not tolerate bullying or abuse. I had considered many possible ways of dealing with this problem, but I will make it simple. Either this man goes, or I do.''

Minerva gasped again. Something strange flickered in Severus's eyes.

Now Dumbledore's gaze was also growing cold. ``Expulsion, Mr. Potter, is the final threat which may be used against a student. It is not customarily used as a threat by students against the Headmaster. This is the best magical school in the entire world, and an education here is not an opportunity given to everyone. Are you under the impression that Hogwarts cannot get along without you?''

And Harry sat there, smiling thinly.

Sudden horror dawned on Minerva. Surely Harry wouldn't -

``You forget,'' Harry said, ``that you're not the only one who can see patterns. \emph{This grows private. Now send him}~-'' Harry flicked a hand at Severus again, and then stopped in mid-sentence and mid-gesture.

Minerva could see it on Harry's face, the moment when he remembered.

She'd told him, after all.

``Mr. Potter,'' said the Headmaster, ``once again, Severus Snape has my fullest confidence.''

``You told him,'' whispered the boy. ``You utter fool.''

Dumbledore didn't react to the insult. ``Told him what?''

``That the Dark Lord is alive.''

``\emph{What in Merlin's name are you on about, Potter?}'' cried Severus in tones of sheer astonishment and outrage.

Harry glanced briefly at him, smiling grimly. ``Oh, so we \emph{are} a Slytherin, then,'' Harry said. ``I was starting to wonder.''

And then there was silence.

Finally Dumbledore spoke. His voice was mild. ``Harry, what \emph{are} you talking about?''

``I'm sorry, Albus,'' Minerva whispered.

Severus and Dumbledore turned to look at her.

``Professor McGonagall didn't tell me,'' said Harry's voice, swiftly and less calm than it had been. ``I guessed. I told you, I can see the patterns too. I guessed, and she controlled her reaction just as Severus did. But her control fell a shade short of perfection, and I could tell it was control, not genuine.''

``And I told him,'' said Minerva, her voice trembling a little, ``that you, and I, and Severus were the only ones who knew.''

``Which she did as a concession to prevent me from simply going around asking questions, as I threatened to do if she didn't talk,'' Harry said. The boy chuckled briefly. ``I really should have gotten one of you alone and told you that she told me everything, to see if you let anything slip. Probably wouldn't have worked, but would have been worth a shot.'' The boy smiled again. ``Threat's still on the table and I do expect to be briefed \emph{fully} at some point.''

Severus was giving her a look of utter contempt. Minerva raised her chin and bore it. She knew it was deserved.

Dumbledore leaned back in his padded throne. His eyes were as cold as anything Minerva had seen from him since the day his brother died. ``And you threaten to abandon us to Voldemort if we do not comply with your wishes.''

Harry's voice was razor-sharp. ``I regret to inform you that you are not the center of the universe. I'm not threatening to walk out on magical Britain. I'm threatening to walk out on \emph{you}. I am not a meek little Frodo. This is \emph{my} quest and if you want in you will play by \emph{my} rules.''

Dumbledore's face was still cold. ``I am beginning to doubt your suitability as the hero, Mr. Potter.''

Harry's return gaze was equally icy. ``I am beginning to doubt your suitability as my Gandalf, \emph{Mr. Dumbledore}. Boromir was at least a plausible mistake. What is this \emph{Nazgul} doing in my Fellowship?''

Minerva was completely lost. She looked at Severus, to see if he was following this, and she saw that Severus had turned his face away from Harry's field of vision and was smiling.

``I suppose,'' Dumbledore said slowly, ``that from your perspective it is a reasonable question. So, Mr. Potter, if Professor Snape is to leave you alone henceforth, will that be the last time this issue arises, or will I find you here every week with a new demand?''

``Leave \emph{me} alone?'' Harry's voice was outraged. ``I am not his only victim and certainly not the most vulnerable! \emph{Have you forgotten how defenseless children are? How much they hurt?} Henceforth Severus will treat \emph{every} student of Hogwarts with appropriate and professional courtesy, or you will find another Potions Master, or you will find another hero!''

Dumbledore started laughing. Full-throated, warm, humorous laughter, as if Harry had just performed a comic dance in front of him.

Minerva didn't dare move. Her eyes flickered and she saw that Severus was equally motionless.

Harry's visage grew even colder. ``You mistake me, Headmaster, if you think that this is a joke. This is not a request. This is your punishment.''

``Mr. Potter~-'' Minerva said. She didn't even know what she was going to say. She simply couldn't let that go by.

Harry made a shushing gesture at her and continued to speak to Dumbledore. ``And if that seems impolite to you,'' Harry said, his voice now a little less hard, ``it seemed no less impolite when you said it to me. You would not say such a thing to anyone who you considered a real human being instead of a subordinate child, and I will treat you with just the same courtesy as you treat me~-''

``Oh, indeed, in very deed, this is my punishment if ever there was one! Of \emph{course} you're in here blackmailing me to save your fellow students, not to save yourself! I can't imagine why I would have thought otherwise!'' Dumbledore was now laughing even harder. He pounded his fist on the desk three times.

Harry's gaze grew uncertain. His face turned toward her, addressing her for the first time. ``Excuse me,'' Harry said. His voice seemed to be wavering. ``Does he need to take his medication or something?''

``Ah...'' Minerva had no idea what she could possibly say.

``Well,'' said Dumbledore. He wiped away tears that had formed in his eyes. ``Pardon me. I'm sorry for the interruption. Please continue with the blackmail.''

Harry opened his mouth, then closed it again. He now seemed a little unsteady. ``Ah... he's also to stop reading students' minds.''

``Minerva,'' Severus said, his voice deadly, ``you~-''

``Sorting Hat warned me,'' said Harry.

``\emph{What?}''

``Can't say anything else. Anyway I think that's it. I'm done.''

Silence.

``Now what?'' Minerva said, when it became apparent that no one else was going to say anything.

``Now what?'' Dumbledore echoed. ``Why, now the hero wins, of course.''

``\emph{What?}'' said Severus, Minerva, and Harry.

``Well, he certainly seems to have backed us into a corner,'' Dumbledore said, smiling happily. ``But Hogwarts \emph{does} need an evil Potions Master, or it just wouldn't be a proper magical school, now would it? So how about if Professor Snape is only awful toward students in their fifth year and higher?''

``\emph{What?}'' said all three of them again.

``If it's the most vulnerable victims about whom you're concerned. Maybe you're right, Harry. Maybe I \emph{have} forgotten over the decades what it's like to be a child. So let's compromise. Severus will continue to unfairly award points to Slytherin and impose lax discipline on his House, and he will be awful to non-Slytherin students in their fifth year and higher. To others he will be scary, but not abusive. He will promise to only read minds when the safety of a student requires it. Hogwarts will have its evil Potions Master, and the most vulnerable victims, as you put it, will be safe.''

Minerva McGonagall was as shocked as she'd ever been in her life. She glanced uncertainly at Severus, whose face had been left completely neutral, as though he couldn't decide what sort of expression he ought to be wearing.

``I suppose that is acceptable,'' Harry said. His voice sounded a bit odd.

``You can't be serious,'' Severus said, his voice as expressionless as his face.

``I am very much in favor of this,'' Minerva said slowly. She was so much in favor that her heart was pounding wildly beneath her robes. ``But what could we possibly tell the students? They might not have questioned this while Severus was... being awful to everyone, but~-''

``Harry can tell the other students that he discovered a terrible secret of Severus's and did a bit of blackmail,'' said Dumbledore. ``It's true, after all; he discovered that Severus was reading minds, and he certainly did blackmail us.''

``This is insanity!'' exploded Severus.

``Bwah ha ha!'' said Dumbledore.

``Ah...'' said Harry uncertainly. ``And if anyone asks me why fifth years and above got shafted? I wouldn't blame them for being irate, and that part wasn't exactly my idea~-''

``Tell them,'' said Dumbledore, ``that it wasn't you who suggested the compromise, that it was all you could get. And then refuse to say anything more. That, too, is true. There's an art to it, you'll pick it up with practice.''

Harry nodded slowly. ``And the points he took from Ravenclaw?''

``They must not be given back.''

It was Minerva who said it.

Harry looked at her.

``I'm sorry, Mr. Potter,'' she said. She \emph{was} sorry, but it had to be done. ``There \emph{must} be some consequences for your misbehavior or this school will fall to pieces.''

Harry shrugged. ``Acceptable,'' he said flatly. ``But in the future Severus will not strike at my House connections by taking points from me, nor will he waste my valuable time with detentions. Should he feel that my behavior requires correction, he may communicate his concerns to Professor McGonagall.''

``Harry,'' Minerva said, ``will you continue to submit to school discipline, or are you to be above the law now, as Severus was?''

Harry looked at her. Something warm touched his gaze, briefly before it was quashed. ``I will continue to be an ordinary student to every member of the staff who is not insane or evil, provided that they do not come under pressure from others who are.'' Harry glanced briefly at Severus, then turned back to Dumbledore. ``Leave Minerva alone, and I'll be a regular Hogwarts student in her presence. No special privileges or immunities.''

``Beautiful,'' Dumbledore said sincerely. ``Spoken like a true hero.''

``And,'' she said, ``Mr. Potter must publicly apologize for his actions of today.''

Harry gave her another look. This one was a bit skeptical.

``The discipline of the school has been gravely injured by your actions, Mr. Potter,'' Minerva said. ``It must be restored.''

``I think, Professor McGonagall, that you considerably overestimate the importance of what you call school discipline, as compared to having History taught by a live teacher or not torturing your students. Maintaining the current status hierarchy and enforcing its rules seems ever so much more wise and moral and important when you are on the top and doing the enforcing than when you are on the bottom, and I can cite studies to this effect if required. I could go on for several hours about this point, but I will leave it at that.''

Minerva shook her head. ``Mr. Potter, you underestimate the importance of discipline because you are not in need of it yourself~-'' She paused. That hadn't come out right, and Severus, Dumbledore, and even Harry were giving her strange looks. ``To learn, I mean. Not every child can learn in the absence of authority. And it is the other children who will be hurt, Mr. Potter, if they see your example as one to be followed.''

Harry's lips curved into a twisted smile. ``The first and last resort is the truth. The truth is that I shouldn't have gotten angry, I shouldn't have disrupted the class, I shouldn't have done what I did, and I set a bad example for everyone. The truth is also that Severus Snape behaved in a fashion unbecoming a Hogwarts professor, and that from now on he will be more mindful of the injured feelings of students in their fourth year and under. The two of us could both get up and speak the truth. I could live with that.''

``In your dreams, Potter!'' spat Severus.

``After all,'' said Harry, smiling grimly, ``if the students see that rules are for \emph{everyone...} for professors too, not just for poor helpless students who get nothing but suffering out of the system... why, the positive effects on school discipline should be \emph{tremendous.}''

There was a brief pause, and then Dumbledore chuckled. ``Minerva is thinking that you're righter than you have any right to be.''

Harry's gaze jerked away from Dumbledore, down to the floor. ``Are \emph{you} reading \emph{her} mind?''

``Common sense is often mistaken for Legilimency,'' said Dumbledore. ``I shall talk over this matter with Severus, and no apology will be required from you unless he apologizes as well. And now I declare this matter concluded, at least until lunchtime.'' He paused. ``Although, Harry, I'm afraid that Minerva wished to speak with you about an additional matter. And that is not the result of any pressure on my part. Minerva, if you would?''

Minerva rose from her chair and almost fell. There was too much adrenaline in her blood, her heart was beating too fast.

``Fawkes,'' said Dumbledore, ``accompany her, please.''

``I don't~-'' she started to say.

Dumbledore shot her a look, and she fell silent.

The phoenix soared across the room like a smooth tongue of flame leaping out, and landed on her shoulder. She felt the warmth through her robes, all through her body.

``Please follow me, Mr. Potter,'' she said, firmly now, and they left through the door.

\begin{center}\rule{3in}{0.4pt}\end{center}

They stood on the rotating stairs, descending in silence.

Minerva didn't know what to say. She didn't know this person who stood beside her.

And Fawkes began to croon.

It was tender, and soft, like a fireplace would sound if it had melody, and it washed over Minerva's mind, easing, soothing, gentling what it touched...

``\emph{What} is \emph{that?}'' Harry whispered beside her. His voice was unstable, wobbling, changing pitch.

``The song of the phoenix,'' said Minerva, not really aware of what she was saying, her attention was all on that strange quiet music. ``It, too, heals.''

Harry turned his face from her, but she caught a glimpse of something agonized.

The descent seemed to take a very long time, or maybe it was only that the music seemed to take a very long time, and when they stepped out through the gap where a gargoyle had been, she was holding Harry's hand firmly in hers.

As the gargoyle stepped back into place, Fawkes left her shoulder, and swooped to hover in front of Harry.

Harry stared at Fawkes like someone hypnotized by the ever-changing light of a fire.

``What am I to do, Fawkes?'' whispered Harry. ``I couldn't have protected them if I hadn't been angry.''

The phoenix's wings continued flapping, it continued hovering in place. There was no sound but the beating of the wings. Then there was a flash like a fire flaring up and going out, and Fawkes was gone.

Both of them blinked, like waking up from a dream, or maybe like falling asleep again.

Minerva looked down.

Harry Potter's bright young face looked up at her.

``Are phoenixes people?'' said Harry. ``I mean, are they smart enough to count as people? Could I talk with Fawkes if I knew how?''

Minerva blinked hard. Then she blinked again. ``No,'' Minerva said, her voice wavering. ``Phoenixes are creatures of powerful magic. That magic gives their existence a weight of meaning which no simple animal could possess. They are fire, light, healing, rebirth. But in the end, no.''

``Where can I get one?''

Minerva leaned down and hugged him. She hadn't meant to, but she didn't seem to have much choice in the matter.

When she stood up she found it hard to speak. But she had to ask. ``What happened today, Harry?''

``I don't know the answers to any of the important questions either. Aside from that I'd really rather not think about it for a while.''

Minerva took his hand in hers again, and they walked the rest of the way in silence.

It was only a short trip, since naturally the office of the Deputy was close to the office of the Headmaster.

Minerva sat behind her desk.

Harry sat in front of her desk.

``So,'' Minerva whispered. She would have given almost anything not to do this, or not to be the one who had to do it, or for it to be any time but right now. ``There is a matter of school discipline. From which you are not exempt.''

``Namely?'' said Harry.

He didn't know. He hadn't figured it out yet. She felt her throat tighten. But there was work to be done and she would not shirk it.

``Mr. Potter,'' said Professor McGonagall, ``I need to see your Time-Turner, please.''

All the peace of the phoenix vanished from his face in an instant and Minerva felt like she had just stabbed him.

``\emph{No!}'' Harry said. His voice was panicked. ``I need it, I won't be able to attend Hogwarts, I won't be able to sleep!''

``You'll be able to sleep,'' she said. ``The Ministry has delivered the protective shell for your Time-Turner. I will enchant it to open only between the hours of 9PM and midnight.''

Harry's face twisted. ``But~--- but I~-''

``Mr. Potter, how many times have you used the Time-Turner since Monday? How many hours?''

``I...'' Harry said. ``Hold on, let me add it up~-'' He glanced down at his watch.

Minerva felt a rush of sadness. She'd thought so. ``It wasn't just two per day, then. I suspect that if I asked your dormmates, I would find that you were struggling to stay up long enough to go to sleep at a reasonable time, and waking up earlier and earlier every morning. Correct?''

Harry's face said everything she needed to know.

``Mr. Potter,'' she said gently, ``there are students who cannot be entrusted with Time-Turners, because they become addicted to them. We give them a potion which lengthens their sleep cycle by the necessary amount, but they end up using the Time-Turner for more than just attending their classes. And so we must take them back. Mr. Potter, you have taken to using the Time-Turner as your solution to everything, often very foolishly so. You used it to get back a Remembrall. You vanished from a closet in a fashion apparent to other students, instead of going back after you were out and getting me or someone else to come and open the door.''

From the look on Harry's face he hadn't thought of that.

``And more importantly,'' she said, ``you should have simply sat in Professor Snape's class. And watched. And left at the end of class. As you would have done if you had not possessed a Time-Turner. There are some students who cannot be entrusted with Time-Turners, Mr. Potter. You are one of them. I am sorry.''

``But I \emph{need} it!'' Harry blurted. ``What if there are Slytherins threatening me and I have to escape? It keeps me \emph{safe}~-''

``Every other student in this castle runs the same risk, and I assure you that they survive. No student has died in this castle for fifty years. Mr. Potter, you will hand over your Time-Turner and do so now.''

Harry's face twisted in agony, but he drew out the Time-Turner from under his robes and gave it to her.

From her desk, Minerva drew out one of the protective shells that had been sent to Hogwarts. She snapped the cover into place around the Time-Turner's turning hourglass, and then she laid her wand on the cover to complete the enchantment.

``\emph{This isn't fair!}'' Harry shrieked. ``I saved half of Hogwarts from Professor Snape today, is it right that I be punished for it? I saw the look on your face, you \emph{hated} what he was doing!''

Minerva didn't speak for a few moments. She was enchanting.

When she finished and looked up, she knew that her face was stern. Maybe it was the wrong thing to do. And then again maybe it was the right thing to do. There was an obstinate child in front of her, and that \emph{didn't} mean the universe was broken.

``\emph{Fair,} Mr. Potter?'' she snapped. ``I have had to file \emph{two reports} with the Ministry on public use of a Time-Turner in \emph{two successive days!} Be \emph{extremely} grateful you were allowed to retain the Time-Turner even in restricted form! The Headmaster made a Floo call to plead with them personally and if you were not the Boy-Who-Lived even that would not have sufficed!''

Harry gaped at her.

She knew that he was seeing the angry face of Professor McGonagall.

Harry's eyes filled up with tears.

``I'm, sorry,'' he whispered, voice now choked and broken. ``I'm sorry, to have, disappointed you...''

``I'm sorry too, Mr. Potter,'' she said sternly, and handed him the newly restricted Time-Turner. ``You may go.''

Harry turned and fled from her office, sobbing. She heard his feet pattering away down the hall, and then the sound cut off as the door swung closed.

``I'm sorry too, Harry,'' she whispered to the quiet room. ``I'm sorry too.''

\begin{center}\rule{3in}{0.4pt}\end{center}

Fifteen minutes into lunch hour.

No one was speaking to Harry. Some of the Ravenclaws were shooting him looks of anger, others of sympathy, a few of the youngest students even had looks of admiration, but no one was talking to him. Even Hermione hadn't tried to come over.

Fred and George had gingerly stepped near. They hadn't said anything. The offer was clear, and its optionality. Harry had told them that he would come over when dessert started, no earlier. They had nodded and quickly walked away.

It was probably the utterly expressionless look on Harry's face that was doing it.

The others probably thought he was controlling anger, or dismay. They knew, because they'd seen Flitwick come and get him, that he'd been called to the Headmaster's office.

Harry was trying not to smile, because if he smiled, he would start laughing, and if he started laughing, he wouldn't stop until the nice people in white jackets came to haul him away.

It was too much. It was just all too much. Harry had almost gone over to the Dark Side, his dark side had done things that seemed in retrospect insane, his dark side had won an impossible victory that might have been real and might have been a pure whim of a crazy Headmaster, his dark side had protected his friends. He just couldn't handle it any more. He needed Fawkes to sing to him again. He needed to use the Time-Turner to go off and take a quiet hour to recover but that wasn't an option any more and the loss was like a hole in his existence but he couldn't think about that because then he might start laughing.

Twenty minutes. All the students who were going to eat lunch had arrived, almost none had departed.

The tapping of a spoon rang through the Great Hall.

``If I may have your attention please,'' Dumbledore said. ``Harry Potter has something he would like to share with us.''

Harry took a deep breath and got up. He walked over to the Head Table, with every eye staring at him.

Harry turned and looked out at the four tables.

It was becoming harder and harder not to smile, but Harry kept his face expressionless as he spoke his brief and memorized speech.

``The truth is sacred,'' Harry said tonelessly. ``One of my most treasured possessions is a button which reads `Speak the truth, even if your voice trembles'. This, then, is the truth. Remember that. I am not saying it because I am being forced to say it, I am saying it because it is true. What I did in Professor Snape's class was foolish, stupid, childish, and an inexcusable violation of the rules of Hogwarts. I disrupted the classroom and deprived my fellow students of their irreplaceable learning time. All because I failed to control my temper. I hope that not a single one of you will ever follow my example. I certainly intend to try never to follow it again.''

Many of the students gazing at Harry now had solemn, unhappy looks upon their faces, such as one might see at a ceremony marking the loss of a fallen champion. At the younger parts of the Gryffindor table the look was almost universal.

Until Harry raised his hand.

He did not raise it high. That might have appeared preemptory. He certainly did not raise it toward Severus. Harry simply raised his hand to chest level, and softly snapped his fingers, a gesture that was seen more than heard. It was possible that most of the Head Table wouldn't see it at all.

This seeming gesture of defiance won sudden smiles from the younger students and Gryffindors, and coldly superior sneers from Slytherin, and frowns and worried looks from all others.

Harry kept his face expressionless. ``Thank you,'' he said. ``That's all.''

``Thank you, Mr. Potter,'' said the Headmaster. ``And now Professor Snape has something to share with us as well.''

Severus smoothly stood up from his place at the Head Table. ``It has been brought to my attention,'' he said, ``that my own actions played a part in provoking the admittedly inexcusable anger of Mr. Potter, and in the ensuing discussion I realized that I had forgotten how easily injured are the feelings of the young and immature~-''

There was the sound of many people emitting muffled chokes at the same time.

Severus continued as if he had not heard. ``The Potions classroom is a dangerous place, and I still feel that strict discipline is necessary, but henceforth I will be more aware of the... emotional fragility... of students in their fourth year and younger. My deduction of points from Ravenclaw still stands, but I will revoke Mr. Potter's detention. Thank you.''

There was a single clap from the direction of Gryffindor and faster than lightning Severus's wand was in his hand and ``\emph{Quietus!}'' silenced the offender.

``I will still demand discipline and respect in \emph{all} my classes,'' Severus said coldly, ``and anyone who trifles with me will regret it.''

He sat down.

``Thank you too!'' Headmaster Dumbledore said cheerfully. ``Carry on!''

And Harry, still expressionless, began to walk back to his seat in Ravenclaw.

There was an explosion of conversation. Two words were clearly identifiable in the beginning. The first was an initial ``What~-'' beginning many different sentences such as ``What just happened~-'' and ``What the hell~-'' The second was ``\emph{Scourgify!}'' as students cleaned up the dropped food and spit-out drinks from themselves, the tablecloth, and each other.

Some students were weeping openly. So was Professor Sprout.

At the Gryffindor table, where a cake waited with fifty-one unlit candles, Fred whispered, ``I think we may be out of our league here, George.''

And from that day onward, no matter what Hermione tried to tell anyone, it would be an accepted legend of Hogwarts that Harry Potter could make absolutely anything happen by snapping his fingers.