/**
  * Initialize and set up the transport layer
  *
  * @param Instance $instance
  *
  * @return $this
  */
 public function connect(Instance $instance)
 {
     $this->instance = $instance;
     $this->token = $this->generateToken([$instance->cluster->cluster_id_text, $instance->instance_id_text]);
     $this->resourceUri = Uri::segment([$instance->getProvisionedEndpoint(), $instance->getResourceUri()], false);
     return $this;
 }
 /**
  * Registers an instance
  *
  * @param \DreamFactory\Enterprise\Database\Models\Instance $instance
  *
  * @return bool|mixed|\stdClass
  */
 public function registerInstance(Instance $instance)
 {
     //  Get url and send data
     if (null === ($_url = config('license.endpoints.instance'))) {
         \Log::warning('[dfe.license] No "instance" license endpoint configured.');
         return false;
     }
     return $this->postData($_url, $instance->toArray());
 }
 /**
  * Initialize and set up the transport layer
  *
  * @param Instance    $instance
  * @param string|null $token  The token to use instead of automatic one
  * @param string|null $header The HTTP header to use instead of DFE one
  *
  * @return $this
  */
 public function connect(Instance $instance, $token = null, $header = null)
 {
     $this->instance = $instance;
     //  Note trailing slash added...
     $this->resourceUri = rtrim(Uri::segment([$instance->getProvisionedEndpoint(), $instance->getResourceUri()], false), '/') . '/';
     //  Set up the channel
     $this->token = $token ?: $this->generateToken([$instance->cluster->cluster_id_text, $instance->instance_id_text]);
     $this->headers = [$header ?: EnterpriseDefaults::CONSOLE_X_HEADER . ': ' . $this->token];
     return $this;
 }
 /**
  * Display a listing of the resource.
  *
  * @return Response
  */
 protected function _loadData()
 {
     $_columns = ['instance_t.id', 'instance_t.instance_id_text', 'cluster_t.cluster_id_text', 'instance_t.create_date', 'user_t.email_addr_text', 'user_t.lmod_date'];
     /** @type Builder $_query */
     $_query = Instance::join('user_t', 'instance_t.user_id', '=', 'user_t.id')->join('cluster_t', 'instance_t.cluster_id', '=', 'cluster_t.id')->select($_columns);
     return $this->processDataRequest('instance_t', Instance::count(), $_columns, $_query);
 }
 /**
  * Get the current status of an instance
  *
  * @param Instance $instance
  *
  * @return array
  */
 public function status($instance)
 {
     /** @var Instance $_instance */
     if (null === ($_instance = Instance::find($instance->id))) {
         return ['success' => false, 'error' => ['code' => 404, 'message' => 'Instance not found.']];
     }
     return ['success' => true, 'status' => $_instance->state_nbr, 'status_text' => ProvisionStates::prettyNameOf($_instance->state_nbr)];
 }
 /**
  * Tests provision request
  */
 public function testProvision()
 {
     $_instanceId = 'bender';
     /** @var Instance $_instance */
     if (null !== ($_instance = Instance::byNameOrId($_instanceId)->first())) {
         $_instance->delete();
     }
     $_payload = ['instance-id' => $_instanceId, 'owner-id' => '*****@*****.**', 'guest-location' => GuestLocations::DFE_CLUSTER];
     \Artisan::call('dfe:provision', $_payload);
 }
 /**
  * Tests provision request
  */
 public function testProvision()
 {
     $_instanceId = 'dfe-test-case';
     $_payload = ['instance-id' => $_instanceId, 'owner-id' => 1, 'guest-location' => GuestLocations::DFE_CLUSTER];
     /** @var Instance $_instance */
     if (null !== ($_instance = Instance::byNameOrId($_instanceId)->first())) {
         $_instance->delete();
     }
     $_job = new ProvisionJob($_instanceId, $_payload);
     $_result = \Queue::push($_job);
 }
 /**
  * Tests provision request
  */
 public function testImport()
 {
     $_instanceId = 'jablan';
     $_snapshotId = '20150824141112.jablan';
     try {
         Instance::byNameOrId($_instanceId)->firstOrFail();
         throw new \RuntimeException('The instance "' . $_instanceId . '" already exists.');
     } catch (ModelNotFoundException $_ex) {
         //  Good
     }
     $_payload = ['instance-id' => $_instanceId, 'snapshot' => $_snapshotId, 'owner-id' => 1, '--owner-type' => OwnerTypes::USER, '--snapshot-id' => true];
     $_result = \Artisan::call('dfe:import', $_payload);
 }
Exemple #9
0
 /**
  * @param Instance $instance
  * @param string   $subject
  * @param array    $data
  *
  * @return int The number of recipients mailed
  */
 protected function notifyInstanceOwner($instance, $subject, array $data)
 {
     try {
         if (!empty($this->subjectPrefix)) {
             $subject = $this->subjectPrefix . ' ' . trim(str_replace($this->subjectPrefix, null, $subject));
         }
         $data['dashboard_url'] = config('dfe.dashboard-url');
         $data['support_email_address'] = config('dfe.support-email-address');
         $_result = \Mail::send('emails.generic', $data, function ($message) use($instance, $subject) {
             $message->to($instance->user->email_addr_text, $instance->user->first_name_text . ' ' . $instance->user->last_name_text)->subject($subject);
         });
         $this instanceof Lumberjack && $this->debug('notification sent to "' . $instance->user->email_addr_text . '"');
         return $_result;
     } catch (\Exception $_ex) {
         \Log::error('Error sending notification: ' . $_ex->getMessage());
         $_mailPath = storage_path('logs/unsent-mail');
         if (!is_dir($_mailPath)) {
             mkdir($_mailPath, 0777, true);
         }
         @file_put_contents(date('YmdHis') . '-' . $instance->user->email_addr_text . '.json', Json::encode(array_merge($data, ['subject' => $subject, 'template' => 'emails.generic', 'instance' => $instance->toArray()])));
         return false;
     }
 }
 /**
  * Returns an array of the instances assigned to a cluster
  *
  * @param int|string $clusterId The cluster ID
  *
  * @return array
  */
 public function getInstances($clusterId)
 {
     $_cluster = $this->_findCluster($clusterId);
     $_rows = Instance::byClusterId($_cluster->id)->get(['id', 'instance_name_text']);
     $_response = [];
     /** @type Instance $_instance */
     foreach ($_rows as $_instance) {
         $_response[] = ['id' => $_instance->id, 'name' => $_instance->instance_name_text];
     }
     //$this->debug('found ' . count($_response) . ' instance(s)');
     usort($_response, function ($a, $b) {
         return strcasecmp($a['name'], $b['name']);
     });
     return $_response;
 }
 /**
  * Handle the command
  *
  * @return mixed
  */
 public function fire()
 {
     parent::fire();
     $_instanceId = $this->argument('instance-id');
     //	Check the name here for quicker response...
     if (false === ($_instanceName = Instance::isNameAvailable($_instanceId)) || is_numeric($_instanceName[0])) {
         $this->error('The name of your instance cannot be "' . $_instanceId . '".  It is either currently in-use, or otherwise invalid.');
         exit(1);
     }
     $_ownerType = OwnerTypes::USER;
     $_ownerId = $this->argument('owner-id');
     $_guestLocation = $this->argument('guest-location');
     $_owner = $this->_locateOwner($_ownerId, $_ownerType);
     $this->writeln('Provisioning instance <comment>"' . $_instanceId . '"</comment>.');
     return \Queue::push(new ProvisionJob($_instanceId, ['guest-location' => $_guestLocation, 'owner-id' => $_owner->id, 'owner-type' => $_ownerType ?: OwnerTypes::USER, 'cluster-id' => $this->option('cluster-id')]));
 }
 /**
  * @param string|Instance $instanceId
  *
  * @return \DreamFactory\Enterprise\Database\Models\Instance
  * @throws \DreamFactory\Enterprise\Database\Exceptions\InstanceNotFoundException
  */
 protected function _validateInstance($instanceId)
 {
     if ($instanceId instanceof Instance) {
         return $instanceId;
     }
     if ($instanceId instanceof InstanceAware) {
         return $instanceId->getInstance();
     }
     if (!is_string($instanceId)) {
         throw new InstanceNotFoundException($instanceId);
     }
     try {
         $instanceId = Instance::sanitizeName($instanceId);
         return Instance::byNameOrId($instanceId)->firstOrFail();
     } catch (\Exception $_ex) {
         throw new InstanceNotFoundException($instanceId);
     }
 }
 /**
  * Migrates all instances known, or in a cluster
  */
 protected function migrateAllInstances()
 {
     if (null !== ($_clusterId = $this->option('cluster-id'))) {
         $_instances = $this->findClusterInstances($_clusterId, ['instance_id_text']);
     } else {
         $_instances = Instance::orderBy('instance_id_text')->get(['instance_id_text']);
     }
     $_results = [];
     if (!empty($_instances)) {
         foreach ($_instances as $_instance) {
             $_id = $_instance->instance_id_text;
             try {
                 $_results[$_id] = $this->migrateSingleInstance($_id);
                 $this->info('* <comment>' . $_id . ':</comment> <info>success</info>');
             } catch (\Exception $_ex) {
                 $_results[$_id] = ['success' => false, 'output' => $_ex->getMessage(), 'exit_code' => $_ex->getCode()];
                 $this->info('* <comment>' . $_id . ':</comment> <error>failure</error>');
             }
         }
     }
     return $_results;
 }
 /**
  * Returns a path where you can write instance-specific temporary data
  *
  * @param \DreamFactory\Enterprise\Database\Models\Instance $instance
  * @param string|null                                       $append Optional appendage to path
  *
  * @return string
  * @throws DiskException
  */
 public function getWorkPath(Instance $instance, $append = null)
 {
     $this->buildStorageMap($instance->user->storage_id_text);
     //  Try private temp path or default to system temp
     if (false === ($_workPath = Disk::path([$instance->getPrivatePath(), 'tmp', $append], true))) {
         $_workPath = Disk::path([sys_get_temp_dir(), 'dfe', $instance->instance_id_text, $append], true);
         if (!$_workPath) {
             throw new DiskException('Unable to locate a suitable temporary directory.');
         }
     }
     return $_workPath;
 }
    /**
     * Creates an export of a instance
     *
     * @param Instance   $instance    The instance of the exports
     * @param array      $exports     Array of files to include in the snapshot
     * @param Filesystem $destination The destination upon which to place the export. Currently unused
     *                                If null, the instance's snapshot storage area is used.
     * @param int        $keepDays    The number of days to keep the snapshot
     *
     * @return array|boolean The snapshot metadata array or false on failure.
     */
    public function createFromExports(Instance $instance, array $exports, Filesystem $destination = null, $keepDays = EnterpriseDefaults::SNAPSHOT_DAYS_TO_KEEP)
    {
        //  Build our "mise en place", as it were...
        $_success = false;
        $_stamp = date('YmdHis');
        //  Create the snapshot ID
        $_snapshotId = $_stamp . '.' . Inflector::neutralize($instance->instance_name_text);
        $_snapshotName = str_replace('{id}', $_snapshotId, config('snapshot.templates.snapshot-file-name'));
        //  Set up the temp dir
        $this->setWorkPath($instance->getSnapshotPath());
        //  Create the snapshot archive and stuff it full of goodies
        /** @var SnapshotManifest $_manifest */
        list($_fsSnapshot, $_manifest, $_routeHash, $_routeLink) = $this->createExportArchive($_snapshotId, $_snapshotName, ['timestamp' => $_stamp, 'guest-location' => $instance->guest_location_nbr, 'instance-id' => $instance->instance_id_text, 'cluster-id' => (int) $instance->cluster_id, 'db-server-id' => (int) $instance->db_server_id, 'web-server-id' => (int) $instance->web_server_id, 'app-server-id' => (int) $instance->app_server_id, 'owner-id' => (int) $instance->user->id, 'owner-email-address' => $instance->user->email_addr_text, 'owner-storage-key' => $instance->user->storage_id_text, 'storage-key' => $instance->storage_id_text], $keepDays);
        try {
            $this->addFilesToArchive($exports, $_fsSnapshot);
            try {
                //  Write our snapshot manifesto
                $_manifest->write();
                //  Close up the files
                /** @noinspection PhpUndefinedMethodInspection */
                $this->flushZipArchive($_fsSnapshot);
                //  Look up the hash entry
                if (null === ($_routeHash = RouteHash::byHash($_routeHash)->first())) {
                    throw new \LogicException('Previously created route hash not found.');
                }
                //  Create our snapshot record
                Snapshot::create(['user_id' => $instance->user_id, 'instance_id' => $instance->id, 'route_hash_id' => $_routeHash->id, 'snapshot_id_text' => $_snapshotId, 'public_ind' => true, 'public_url_text' => $_routeLink, 'expire_date' => $_routeHash->expire_date]);
                //  Copy to $destination if requested
                if ($destination) {
                    if (false === ($_fd = fopen($this->workPath . $_snapshotName, 'r'))) {
                        throw new FileSystemException('Unable to open export file "' . $this->workPath . $_snapshotName . '".');
                    }
                    $destination->putStream($_snapshotName, $_fd);
                    fclose($_fd);
                }
                //  Let the user know...
                $this->notifyInstanceOwner($instance, 'Export successful', ['firstName' => $instance->user->first_name_text, 'headTitle' => 'Export Complete', 'contentHeader' => 'Your export has completed', 'emailBody' => <<<HTML
<p>Your export is complete. It may be downloaded it for up to {$keepDays} days, from the following link:<br/>
<br/>
<strong><a href="{$_routeLink}" target="_blank">{$_routeLink}</a></strong>
</p>
HTML
]);
                $_success = true;
            } catch (\Exception $_ex) {
                $this->error('exception building snapshot archive: ' . $_ex->getMessage());
                throw $_ex;
            }
        } catch (\Exception $_ex) {
            $this->error('exception during sub-provisioner export call: ' . $_ex->getMessage());
            $this->notifyInstanceOwner($instance, 'Export failure', ['firstName' => $instance->user->first_name_text, 'headTitle' => 'Export Failure', 'contentHeader' => 'Your export was not created', 'emailBody' => <<<HTML
<p>The export requested did not complete properly. Please make sure your instance is up and running, then try again. If the issue persists, please contact support.</p>
HTML
]);
            $_success = false;
        } finally {
            //  Cleanup
            $_fsSnapshot = null;
        }
        return $_success ? $_manifest->toArray() : false;
    }
 /**
  * @return array
  */
 protected function gatherInstanceStatistics()
 {
     $_stats = [];
     $_lastGuestLocation = null;
     /** @type Instance $_instance */
     foreach (Instance::all() as $_instance) {
         $_stats[$_instance->instance_id_text] = ['uri' => $_instance->getProvisionedEndpoint()];
         $_api = InstanceApiClient::connect($_instance);
         try {
             if (!empty($_resources = $_api->resources())) {
                 $_list = [];
                 foreach ($_resources as $_resource) {
                     if (property_exists($_resource, 'name')) {
                         try {
                             if (false !== ($_result = $_api->resource($_resource->name))) {
                                 $_list[$_resource->name] = count($_result);
                             }
                         } catch (\Exception $_ex) {
                             $_list[$_resource->name] = 'unavailable';
                         }
                     }
                 }
                 $_stats[$_instance->instance_id_text]['resources'] = $_list;
                 $_stats[$_instance->instance_id_text]['_status'] = ['operational'];
             }
         } catch (\Exception $_ex) {
             //  Instance unavailable or not initialized
             $_stats[$_instance->instance_id_text]['resources'] = [];
             $_stats[$_instance->instance_id_text]['_status'] = ['unreachable'];
         }
     }
     return $_stats;
     //  The new way
     //return $this->telemetry->make('instance')->getTelemetry();
 }
 /**
  * Generates a unique db-name/user/pass for MySQL for an instance
  *
  * @param Instance $instance
  *
  * @return array
  * @throws SchemaExistsException
  */
 protected function generateSchemaCredentials(Instance $instance)
 {
     $_tries = 0;
     $_dbUser = null;
     $_dbName = $this->generateDatabaseName($instance);
     $_seed = $_dbName . env('APP_KEY') . $instance->instance_name_text;
     //  Make sure our user name is unique...
     while (true) {
         $_baseHash = sha1(microtime(true) . $_seed);
         $_dbUser = substr('u' . $_baseHash, 0, 16);
         if (0 == Instance::where('db_user_text', '=', $_dbUser)->count()) {
             $_sql = 'SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = :schema_name';
             //  Make sure the database name is unique as well.
             /** @noinspection PhpUndefinedMethodInspection */
             $_names = DB::select($_sql, [':schema_name' => $_dbName]);
             if (!empty($_names)) {
                 throw new SchemaExistsException('The schema "' . $_dbName . '" already exists.');
             }
             break;
         }
         if (++$_tries > 10) {
             throw new \LogicException('Unable to locate a non-unique database user name after ' . $_tries . ' attempts.');
         }
         //  Quick snoozy and we try again
         usleep(500000);
     }
     $_creds = ['database' => $_dbName, 'username' => $_dbUser, 'password' => sha1(microtime(true) . $_seed . $_dbUser . microtime(true))];
     return $_creds;
 }
 /**
  * @param int|string $instanceId
  *
  * @return Instance
  */
 protected static function _lookupInstance($instanceId)
 {
     return Instance::byNameOrId($instanceId)->firstOrFail();
 }
Exemple #19
0
 /**
  * Build the 'paths' section of the metadata
  *
  * @param \DreamFactory\Enterprise\Database\Models\Instance $instance
  *
  * @return array
  */
 protected static function buildPathMetadata(Instance $instance)
 {
     return ['storage-root' => InstanceStorage::getStorageRootPath(), 'storage-path' => $instance->getStoragePath(), 'private-path' => $instance->getPrivatePath(), 'owner-private-path' => $instance->getOwnerPrivatePath(), 'snapshot-path' => $instance->getSnapshotPath(), 'trash-path' => $instance->getTrashPath()];
 }
 /**
  * Create a new instance record
  *
  * @param string $instanceName
  * @param array  $options Array of options for creation. Options are:
  *
  *                        owner-id      The id of the instance owner
  *                        cluster-id    The cluster that owns this instance
  *                        trial         If true, the "trial" flagged is set for the instance
  *
  * @return Instance
  * @throws DuplicateInstanceException
  * @throws ProvisioningException
  */
 public function make($instanceName, $options = [])
 {
     try {
         //  Basic checks...
         if (null === ($_ownerId = array_get($options, 'owner-id'))) {
             throw new \InvalidArgumentException('No "owner-id" given. Cannot create instance.');
         }
         if (null == ($_ownerType = array_get($options, 'owner-type'))) {
             $_ownerType = OwnerTypes::USER;
         }
         try {
             $_owner = OwnerTypes::getOwner($_ownerId, $_ownerType);
         } catch (ModelNotFoundException $_ex) {
             throw new \InvalidArgumentException('The "owner-id" and/or "owner-type" specified is/are invalid.');
         }
         //$this->debug('owner validated: ' . $_owner->id . ($_owner->admin_ind ? ' (admin)' : ' (non-admin)'));
         if (false === ($_sanitized = Instance::isNameAvailable($instanceName, $_owner->admin_ind))) {
             throw new DuplicateInstanceException('The instance name "' . $instanceName . '" is not available.');
         }
         //  Get the proper location
         $_guestLocation = array_get($options, 'guest-location', config('provisioning.default-guest-location'));
         //  Validate the cluster and pull component ids
         $_clusterId = array_get($options, 'cluster-id', config('provisioning.default-cluster-id'));
         $_clusterConfig = $this->getServersForCluster($_clusterId);
         $_ownerId = $_owner->id;
         $_attributes = ['user_id' => (int) $_ownerId, 'instance_id_text' => $_sanitized, 'instance_name_text' => $_sanitized, 'guest_location_nbr' => $_guestLocation, 'cluster_id' => (int) $_clusterConfig['cluster-id'], 'db_server_id' => (int) $_clusterConfig['db-server-id'], 'app_server_id' => (int) $_clusterConfig['app-server-id'], 'web_server_id' => (int) $_clusterConfig['web-server-id'], 'state_nbr' => ProvisionStates::CREATED];
         $_guestAttributes = ['instance_id' => null, 'vendor_id' => $_guestLocation, 'vendor_image_id' => array_get($options, 'vendor-image-id', config('provisioning.default-vendor-image-id')), 'vendor_credentials_id' => array_get($options, 'vendor-credentials-id', config('provisioning.default-vendor-credentials-id'))];
         //  Write it out
         return \DB::transaction(function () use($_ownerId, $_attributes, $_guestAttributes) {
             $_instance = Instance::create($_attributes);
             //$this->debug('created instance row id#' . $_instance->id);
             $_guestAttributes['instance_id'] = $_instance->id;
             $_guest = InstanceGuest::create($_guestAttributes);
             //$this->debug('created guest row id#' . $_guest->id);
             if (!$_instance || !$_guest) {
                 throw new \RuntimeException('Instance creation failed');
             }
             return $_instance;
         });
     } catch (\Exception $_ex) {
         throw new ProvisioningException('Error creating new instance: ' . $_ex->getMessage());
     }
 }
 /**
  * Returns all instances managed by $clusterId
  *
  * @param \DreamFactory\Enterprise\Database\Models\Cluster|int $clusterId
  * @param array                                                $columns The columns to retrieve
  *
  * @return \Illuminate\Support\Collection
  */
 protected static function findClusterInstances($clusterId, $columns = ['*'])
 {
     return Instance::where('cluster_id', static::findCluster($clusterId)->id)->orderBy('instance_id_text')->get($columns);
 }
 public function index()
 {
     return $this->renderView('app.instances', ['instances' => Instance::with(['user', 'cluster'])->get()]);
 }
 /**
  * @param string $instanceId
  * @param bool   $trial
  * @param bool   $remote If true, create instance on user's account
  *
  * @return bool|mixed|\stdClass
  */
 public function provisionInstance($instanceId, $trial = false, $remote = false)
 {
     Flasher::forget();
     $_provisioner = $this->request->input('_provisioner', GuestLocations::DFE_CLUSTER);
     //	Check the name here for quicker UI response...
     if (false === ($_instanceName = Instance::isNameAvailable($instanceId)) || is_numeric($_instanceName[0])) {
         Flasher::setIf('The name of your instance cannot be "' . $instanceId . '".  It is either currently in-use, or otherwise invalid.', false);
         return ErrorPacket::create(null, Response::HTTP_BAD_REQUEST, 'Invalid instance name.');
     }
     if (false === ($_clusterConfig = $this->getClusterConfig())) {
         Flasher::setIf('The DFE Console is not currently available. Please try your request later.', false);
         return ErrorPacket::create(null, Response::HTTP_INTERNAL_SERVER_ERROR, 'Cluster server configuration error.');
     }
     $_payload = array_merge(['instance-id' => $_instanceName, 'trial' => $trial, 'remote' => $remote, 'ram-size' => $this->request->input('ram-size'), 'disk-size' => $this->request->input('disk-size'), 'vendor-id' => $this->request->input('vendor-id'), 'vendor-secret' => $this->request->input('vendor-secret'), 'owner-id' => \Auth::id(), 'owner-type' => OwnerTypes::USER, 'guest-location' => $_provisioner], $_clusterConfig);
     $_result = $this->callConsole('provision', $_payload);
     if ($_result && is_object($_result) && isset($_result->success)) {
         if ($_result->success) {
             Flasher::setIf('Instance provisioning requested successfully.');
         } else {
             if (isset($_result->error)) {
                 $_message = isset($_result->error->message) ? $_result->error->message : 'Unknown error';
             } else {
                 $_message = 'Unknown server error';
             }
             Flasher::setIf($_message, false);
             return ErrorPacket::create(null, Response::HTTP_INTERNAL_SERVER_ERROR, 'Provisioning error.');
         }
     } else {
         Flasher::setIf('The DFE Console is not currently available. Please try your request later.', false);
         $this->error('Error calling ops console api: ' . print_r($_result, true));
         return ErrorPacket::create(null, Response::HTTP_INTERNAL_SERVER_ERROR, 'Cannot connect to ops console.');
     }
     return SuccessPacket::create($_result);
 }
 /**
  * @param Instance $instance
  *
  * @return array
  */
 protected function getStoredData(Instance $instance)
 {
     //  Get our database connection...
     $_db = $instance->instanceConnection($instance);
     //  Get a table list...
     $_tables = $_db->getDoctrineConnection()->getSchemaManager()->listTables();
     $_data = [];
     foreach ($_tables as $_table) {
         $_tableName = $_table->getName();
         //  Get the columns
         $_columns = [];
         foreach ($_table->getColumns() as $_column) {
             $_array = $_column->toArray();
             $_array['type'] = (string) $_array['type'];
             $_columns[] = $_array;
         }
         $_data[$_tableName] = ['schema' => $_columns, 'data' => $_db->select('SELECT * FROM ' . $_tableName)];
     }
     return $_data;
 }